1/*! jQuery UI - v1.8.19 - 2012-04-16 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: "@VERSION", 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$.each( [ "Width", "Height" ], function( i, name ) { 131 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 132 type = name.toLowerCase(), 133 orig = { 134 innerWidth: $.fn.innerWidth, 135 innerHeight: $.fn.innerHeight, 136 outerWidth: $.fn.outerWidth, 137 outerHeight: $.fn.outerHeight 138 }; 139 140 function reduce( elem, size, border, margin ) { 141 $.each( side, function() { 142 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; 143 if ( border ) { 144 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; 145 } 146 if ( margin ) { 147 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; 148 } 149 }); 150 return size; 151 } 152
153 $.fn[ "inner" + name ] = function( size ) { 154 if ( size === undefined ) { 155 return orig[ "inner" + name ].call( this ); 156 } 157 158 return this.each(function() { 159 $( this ).css( type, reduce( this, size ) + "px" ); 160 }); 161 }; 162 163 $.fn[ "outer" + name] = function( size, margin ) { 164 if ( typeof size !== "number" ) { 165 return orig[ "outer" + name ].call( this, size ); 166 } 167 168 return this.each(function() { 169 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 170 }); 171 }; 172}); 173 174// selectors 175function focusable( element, isTabIndexNotNaN ) { 176 var nodeName = element.nodeName.toLowerCase(); 177 if ( "area" === nodeName ) { 178 var map = element.parentNode, 179 mapName = map.name, 180 img; 181 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 182 return false; 183 } 184 img = $( "img[usemap=#" + mapName + "]" )[0]; 185 return !!img && visible( img ); 186 } 187 return ( /input|select|textarea|button|object/.test( nodeName ) 188 ? !element.disabled 189 : "a" == nodeName 190 ? element.href || isTabIndexNotNaN 191 : isTabIndexNotNaN) 192 // the element and all of its ancestors must be visible 193 && visible( element ); 194} 195 196function visible( element ) { 197 return !$( element ).parents().andSelf().filter(function() { 198 return $.curCSS( this, "visibility" ) === "hidden" || 199 $.expr.filters.hidden( this ); 200 }).length; 201} 202 203$.extend( $.expr[ ":" ], { 204 data: function( elem, i, match ) { 205 return !!$.data( elem, match[ 3 ] ); 206 }, 207 208 focusable: function( element ) { 209 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 210 }, 211 212 tabbable: function( element ) { 213 var tabIndex = $.attr( element, "tabindex" ), 214 isTabIndexNaN = isNaN( tabIndex ); 215 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 216 } 217}); 218 219// support 220$(function() { 221 var body = document.body, 222 div = body.appendChild( div = document.createElement( "div" ) ); 223 224 // access offsetHeight before setting the style to prevent a layout bug 225 // in IE 9 which causes the elemnt to continue to take up space even 226 // after it is removed from the DOM (#8026) 227 div.offsetHeight; 228 229 $.extend( div.style, { 230 minHeight: "100px", 231 height: "auto", 232 padding: 0, 233 borderWidth: 0 234 }); 235 236 $.support.minHeight = div.offsetHeight === 100; 237 $.support.selectstart = "onselectstart" in div; 238 239 // set display to none to avoid a layout bug in IE 240 // http://dev.jquery.com/ticket/4014 241 body.removeChild( div ).style.display = "none"; 242}); 243 244 245 246 247 248// deprecated 249$.extend( $.ui, { 250 // $.ui.plugin is deprecated. Use the proxy pattern instead. 251 plugin: { 252 add: function( module, option, set ) { 253 var proto = $.ui[ module ].prototype; 254 for ( var i in set ) { 255 proto.plugins[ i ] = proto.plugins[ i ] || []; 256 proto.plugins[ i ].push( [ option, set[ i ] ] ); 257 } 258 }, 259 call: function( instance, name, args ) { 260 var set = instance.plugins[ name ]; 261 if ( !set || !instance.element[ 0 ].parentNode ) { 262 return; 263 } 264 265 for ( var i = 0; i < set.length; i++ ) { 266 if ( instance.options[ set[ i ][ 0 ] ] ) { 267 set[ i ][ 1 ].apply( instance.element, args ); 268 } 269 } 270 } 271 }, 272 273 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() 274 contains: function( a, b ) { 275 return document.compareDocumentPosition ? 276 a.compareDocumentPosition( b ) & 16 : 277 a !== b && a.contains( b ); 278 }, 279 280 // only used by resizable 281 hasScroll: function( el, a ) { 282 283 //If overflow is hidden, the element might have extra content, but the user wants to hide it 284 if ( $( el ).css( "overflow" ) === "hidden") { 285 return false; 286 } 287 288 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 289 has = false; 290 291 if ( el[ scroll ] > 0 ) { 292 return true; 293 } 294 295 // TODO: determine which cases actually cause this to happen 296 // if the element doesn't have the scroll set, see if it's possible to 297 // set the scroll 298 el[ scroll ] = 1; 299 has = ( el[ scroll ] > 0 ); 300 el[ scroll ] = 0; 301 return has; 302 }, 303
304 // these are odd functions, fix the API or move into individual plugins 305 isOverAxis: function( x, reference, size ) { 306 //Determines when x coordinate is over "b" element axis 307 return ( x > reference ) && ( x < ( reference + size ) ); 308 }, 309 isOver: function( y, x, top, left, height, width ) { 310 //Determines when x, y coordinates is over "b" element 311 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); 312 } 313}); 314 315})( jQuery ); 316 317(function( $, undefined ) { 318 319// jQuery 1.4+ 320if ( $.cleanData ) { 321 var _cleanData = $.cleanData; 322 $.cleanData = function( elems ) { 323 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 324 try { 325 $( elem ).triggerHandler( "remove" ); 326 // http://bugs.jquery.com/ticket/8235 327 } catch( e ) {} 328 } 329 _cleanData( elems ); 330 }; 331} else { 332 var _remove = $.fn.remove; 333 $.fn.remove = function( selector, keepData ) { 334 return this.each(function() { 335 if ( !keepData ) { 336 if ( !selector || $.filter( selector, [ this ] ).length ) { 337 $( "*", this ).add( [ this ] ).each(function() { 338 try { 339 $( this ).triggerHandler( "remove" ); 340 // http://bugs.jquery.com/ticket/8235 341 } catch( e ) {} 342 }); 343 } 344 } 345 return _remove.call( $(this), selector, keepData ); 346 }); 347 }; 348} 349 350$.widget = function( name, base, prototype ) { 351 var namespace = name.split( "." )[ 0 ], 352 fullName; 353 name = name.split( "." )[ 1 ]; 354 fullName = namespace + "-" + name; 355 356 if ( !prototype ) { 357 prototype = base; 358 base = $.Widget; 359 } 360 361 // create selector for plugin 362 $.expr[ ":" ][ fullName ] = function( elem ) { 363 return !!$.data( elem, name ); 364 }; 365 366 $[ namespace ] = $[ namespace ] || {}; 367 $[ namespace ][ name ] = function( options, element ) { 368 // allow instantiation without initializing for simple inheritance 369 if ( arguments.length ) { 370 this._createWidget( options, element ); 371 } 372 }; 373 374 var basePrototype = new base(); 375 // we need to make the options hash a property directly on the new instance 376 // otherwise we'll modify the options hash on the prototype that we're 377 // inheriting from 378// $.each( basePrototype, function( key, val ) { 379// if ( $.isPlainObject(val) ) { 380// basePrototype[ key ] = $.extend( {}, val ); 381// } 382// }); 383 basePrototype.options = $.extend( true, {}, basePrototype.options ); 384 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { 385 namespace: namespace, 386 widgetName: name, 387 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, 388 widgetBaseClass: fullName 389 }, prototype ); 390 391 $.widget.bridge( name, $[ namespace ][ name ] ); 392}; 393 394$.widget.bridge = function( name, object ) { 395 $.fn[ name ] = function( options ) { 396 var isMethodCall = typeof options === "string", 397 args = Array.prototype.slice.call( arguments, 1 ), 398 returnValue = this; 399 400 // allow multiple hashes to be passed on init 401 options = !isMethodCall && args.length ? 402 $.extend.apply( null, [ true, options ].concat(args) ) : 403 options; 404 405 // prevent calls to internal methods 406 if ( isMethodCall && options.charAt( 0 ) === "_" ) { 407 return returnValue; 408 } 409 410 if ( isMethodCall ) { 411 this.each(function() { 412 var instance = $.data( this, name ), 413 methodValue = instance && $.isFunction( instance[options] ) ? 414 instance[ options ].apply( instance, args ) : 415 instance; 416 // TODO: add this back in 1.9 and use $.error() (see #5972) 417// if ( !instance ) { 418// throw "cannot call methods on " + name + " prior to initialization; " + 419// "attempted to call method '" + options + "'"; 420// } 421// if ( !$.isFunction( instance[options] ) ) { 422// throw "no such method '" + options + "' for " + name + " widget instance"; 423// } 424// var methodValue = instance[ options ].apply( instance, args ); 425 if ( methodValue !== instance && methodValue !== undefined ) { 426 returnValue = methodValue; 427 return false; 428 } 429 }); 430 } else { 431 this.each(function() { 432 var instance = $.data( this, name ); 433 if ( instance ) { 434 instance.option( options || {} )._init(); 435 } else { 436 $.data( this, name, new object( options, this ) ); 437 } 438 }); 439 } 440 441 return returnValue; 442 }; 443}; 444 445$.Widget = function( options, element ) { 446 // allow instantiation without initializing for simple inheritance 447 if ( arguments.length ) { 448 this._createWidget( options, element ); 449 } 450}; 451 452$.Widget.prototype = { 453 widgetName: "widget", 454 widgetEventPrefix: "", 455 options: { 456 disabled: false 457 }, 458 _createWidget: function( options, element ) { 459 // $.widget.bridge stores the plugin instance, but we do it anyway 460 // so that it's stored even before the _create function runs 461 $.data( element, this.widgetName, this ); 462 this.element = $( element ); 463 this.options = $.extend( true, {}, 464 this.options, 465 this._getCreateOptions(), 466 options ); 467 468 var self = this; 469 this.element.bind( "remove." + this.widgetName, function() { 470 self.destroy(); 471 }); 472 473 this._create(); 474 this._trigger( "create" ); 475 this._init(); 476 }, 477 _getCreateOptions: function() { 478 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; 479 }, 480 _create: function() {}, 481 _init: function() {}, 482 483 destroy: function() { 484 this.element 485 .unbind( "." + this.widgetName ) 486 .removeData( this.widgetName ); 487 this.widget() 488 .unbind( "." + this.widgetName ) 489 .removeAttr( "aria-disabled" ) 490 .removeClass( 491 this.widgetBaseClass + "-disabled " + 492 "ui-state-disabled" ); 493 }, 494 495 widget: function() { 496 return this.element; 497 }, 498 499 option: function( key, value ) { 500 var options = key; 501 502 if ( arguments.length === 0 ) { 503 // don't return a reference to the internal hash 504 return $.extend( {}, this.options ); 505 } 506 507 if (typeof key === "string" ) { 508 if ( value === undefined ) { 509 return this.options[ key ]; 510 } 511 options = {}; 512 options[ key ] = value; 513 } 514 515 this._setOptions( options ); 516 517 return this; 518 }, 519 _setOptions: function( options ) { 520 var self = this; 521 $.each( options, function( key, value ) { 522 self._setOption( key, value ); 523 }); 524 525 return this; 526 }, 527 _setOption: function( key, value ) { 528 this.options[ key ] = value; 529 530 if ( key === "disabled" ) { 531 this.widget() 532 [ value ? "addClass" : "removeClass"]( 533 this.widgetBaseClass + "-disabled" + " " + 534 "ui-state-disabled" ) 535 .attr( "aria-disabled", value ); 536 } 537 538 return this; 539 }, 540 541 enable: function() { 542 return this._setOption( "disabled", false ); 543 }, 544 disable: function() { 545 return this._setOption( "disabled", true ); 546 }, 547 548 _trigger: function( type, event, data ) { 549 var prop, orig, 550 callback = this.options[ type ]; 551 552 data = data || {}; 553 event = $.Event( event ); 554 event.type = ( type === this.widgetEventPrefix ? 555 type : 556 this.widgetEventPrefix + type ).toLowerCase(); 557 // the original event may come from any element 558 // so we need to reset the target on the new event 559 event.target = this.element[ 0 ]; 560 561 // copy original event properties over to the new event 562 orig = event.originalEvent; 563 if ( orig ) { 564 for ( prop in orig ) { 565 if ( !( prop in event ) ) { 566 event[ prop ] = orig[ prop ]; 567 } 568 } 569 } 570 571 this.element.trigger( event, data ); 572 573 return !( $.isFunction(callback) && 574 callback.call( this.element[0], event, data ) === false || 575 event.isDefaultPrevented() ); 576 } 577}; 578 579})( jQuery ); 580 581(function( $, undefined ) { 582 583var mouseHandled = false; 584$( document ).mouseup( function( e ) { 585 mouseHandled = false; 586}); 587 588$.widget("ui.mouse", { 589 options: { 590 cancel: ':input,option', 591 distance: 1, 592 delay: 0 593 },
vendor: 2,188 bytes, lines 594-660
594 _mouseInit: function() { 595 var self = this; 596 597 this.element 598 .bind('mousedown.'+this.widgetName, function(event) { 599 return self._mouseDown(event); 600 }) 601 .bind('click.'+this.widgetName, function(event) { 602 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { 603 $.removeData(event.target, self.widgetName + '.preventClickEvent'); 604 event.stopImmediatePropagation(); 605 return false; 606 } 607 }); 608 609 this.started = false; 610 }, 611 612 // TODO: make sure destroying one instance of mouse doesn't mess with 613 // other instances of mouse 614 _mouseDestroy: function() { 615 this.element.unbind('.'+this.widgetName); 616 $(document) 617 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 618 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); 619 }, 620 621 _mouseDown: function(event) { 622 // don't let more than one widget handle mouseStart 623 if( mouseHandled ) { return }; 624 625 // we may have missed mouseup (out of window) 626 (this._mouseStarted && this._mouseUp(event)); 627 628 this._mouseDownEvent = event; 629 630 var self = this, 631 btnIsLeft = (event.which == 1), 632 // event.target.nodeName works around a bug in IE 8 with 633 // disabled inputs (#7620) 634 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 635 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 636 return true; 637 } 638 639 this.mouseDelayMet = !this.options.delay; 640 if (!this.mouseDelayMet) { 641 this._mouseDelayTimer = setTimeout(function() { 642 self.mouseDelayMet = true; 643 }, this.options.delay); 644 } 645 646 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 647 this._mouseStarted = (this._mouseStart(event) !== false); 648 if (!this._mouseStarted) { 649 event.preventDefault(); 650 return true; 651 } 652 } 653 654 // Click event may never have fired (Gecko & Opera) 655 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { 656 $.removeData(event.target, this.widgetName + '.preventClickEvent'); 657 } 658 659 // these delegates are required to keep context 660 this._mouseMoveDelegate = function(event) {
661 return self._mouseMove(event); 662 }; 663 this._mouseUpDelegate = function(event) { 664 return self._mouseUp(event); 665 }; 666 $(document) 667 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 668 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); 669 670 event.preventDefault(); 671 672 mouseHandled = true; 673 return true; 674 }, 675 676 _mouseMove: function(event) { 677 // IE mouseup check - mouseup happened when mouse was out of window 678 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { 679 return this._mouseUp(event); 680 } 681 682 if (this._mouseStarted) { 683 this._mouseDrag(event); 684 return event.preventDefault(); 685 } 686 687 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 688 this._mouseStarted = 689 (this._mouseStart(this._mouseDownEvent, event) !== false); 690 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 691 } 692 693 return !this._mouseStarted; 694 }, 695 696 _mouseUp: function(event) { 697 $(document) 698 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 699 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); 700 701 if (this._mouseStarted) { 702 this._mouseStarted = false; 703 704 if (event.target == this._mouseDownEvent.target) { 705 $.data(event.target, this.widgetName + '.preventClickEvent', true); 706 } 707 708 this._mouseStop(event); 709 } 710 711 return false; 712 }, 713 714 _mouseDistanceMet: function(event) { 715 return (Math.max( 716 Math.abs(this._mouseDownEvent.pageX - event.pageX), 717 Math.abs(this._mouseDownEvent.pageY - event.pageY) 718 ) >= this.options.distance 719 ); 720 }, 721 722 _mouseDelayMet: function(event) { 723 return this.mouseDelayMet; 724 }, 725 726 // These are placeholder methods, to be overriden by extending plugin 727 _mouseStart: function(event) {}, 728 _mouseDrag: function(event) {}, 729 _mouseStop: function(event) {}, 730 _mouseCapture: function(event) { return true; } 731}); 732 733})(jQuery); 734 735(function( $, undefined ) { 736 737$.widget("ui.draggable", $.ui.mouse, { 738 widgetEventPrefix: "drag", 739 options: { 740 addClasses: true, 741 appendTo: "parent", 742 axis: false, 743 connectToSortable: false, 744 containment: false, 745 cursor: "auto", 746 cursorAt: false, 747 grid: false, 748 handle: false, 749 helper: "original", 750 iframeFix: false, 751 opacity: false, 752 refreshPositions: false, 753 revert: false, 754 revertDuration: 500, 755 scope: "default", 756 scroll: true, 757 scrollSensitivity: 20, 758 scrollSpeed: 20, 759 snap: false, 760 snapMode: "both", 761 snapTolerance: 20, 762 stack: false, 763 zIndex: false 764 }, 765 _create: function() { 766 767 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) 768 this.element[0].style.position = 'relative'; 769 770 (this.options.addClasses && this.element.addClass("ui-draggable")); 771 (this.options.disabled && this.element.addClass("ui-draggable-disabled")); 772 773 this._mouseInit(); 774 775 }, 776 777 destroy: function() { 778 if(!this.element.data('draggable')) return; 779 this.element 780 .removeData("draggable") 781 .unbind(".draggable") 782 .removeClass("ui-draggable" 783 + " ui-draggable-dragging" 784 + " ui-draggable-disabled"); 785 this._mouseDestroy(); 786 787 return this; 788 }, 789 790 _mouseCapture: function(event) { 791 792 var o = this.options; 793 794 // among others, prevent a drag on a resizable-handle 795 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) 796 return false; 797 798 //Quit if we're not on a valid handle 799 this.handle = this._getHandle(event); 800 if (!this.handle) 801 return false; 802 803 if ( o.iframeFix ) { 804 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 805 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>') 806 .css({ 807 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 808 position: "absolute", opacity: "0.001", zIndex: 1000 809 }) 810 .css($(this).offset()) 811 .appendTo("body"); 812 }); 813 } 814 815 return true; 816 817 }, 818 819 _mouseStart: function(event) { 820 821 var o = this.options; 822 823 //Create and append the visible helper 824 this.helper = this._createHelper(event); 825 826 //Cache the helper size 827 this._cacheHelperProportions(); 828 829 //If ddmanager is used for droppables, set the global draggable 830 if($.ui.ddmanager) 831 $.ui.ddmanager.current = this; 832 833 /* 834 * - Position generation - 835 * This block generates everything position related - it's the core of draggables. 836 */ 837 838 //Cache the margins of the original element 839 this._cacheMargins(); 840 841 //Store the helper's css position 842 this.cssPosition = this.helper.css("position"); 843 this.scrollParent = this.helper.scrollParent(); 844 845 //The element's absolute position on the page minus margins 846 this.offset = this.positionAbs = this.element.offset(); 847 this.offset = { 848 top: this.offset.top - this.margins.top, 849 left: this.offset.left - this.margins.left 850 }; 851 852 $.extend(this.offset, { 853 click: { //Where the click happened, relative to the element 854 left: event.pageX - this.offset.left, 855 top: event.pageY - this.offset.top 856 }, 857 parent: this._getParentOffset(), 858 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 859 }); 860 861 //Generate the original position 862 this.originalPosition = this.position = this._generatePosition(event); 863 this.originalPageX = event.pageX; 864 this.originalPageY = event.pageY; 865 866 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied 867 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
868 869 //Set a containment if given in the options 870 if(o.containment) 871 this._setContainment(); 872 873 //Trigger event + callbacks 874 if(this._trigger("start", event) === false) { 875 this._clear(); 876 return false; 877 } 878 879 //Recache the helper size 880 this._cacheHelperProportions(); 881 882 //Prepare the droppable offsets 883 if ($.ui.ddmanager && !o.dropBehaviour) 884 $.ui.ddmanager.prepareOffsets(this, event); 885 886 this.helper.addClass("ui-draggable-dragging"); 887 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 888 889 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 890 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); 891 892 return true; 893 }, 894 895 _mouseDrag: function(event, noPropagation) { 896 897 //Compute the helpers position 898 this.position = this._generatePosition(event); 899 this.positionAbs = this._convertPositionTo("absolute"); 900 901 //Call plugins and callbacks and use the resulting position if something is returned 902 if (!noPropagation) { 903 var ui = this._uiHash(); 904 if(this._trigger('drag', event, ui) === false) { 905 this._mouseUp({}); 906 return false; 907 } 908 this.position = ui.position; 909 } 910 911 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; 912 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; 913 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); 914 915 return false; 916 }, 917 918 _mouseStop: function(event) { 919 920 //If we are using droppables, inform the manager about the drop 921 var dropped = false; 922 if ($.ui.ddmanager && !this.options.dropBehaviour) 923 dropped = $.ui.ddmanager.drop(this, event); 924 925 //if a drop comes from outside (a sortable) 926 if(this.dropped) { 927 dropped = this.dropped; 928 this.dropped = false; 929 } 930 931 //if the original element is removed, don't bother to continue if helper is set to "original" 932 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original") 933 return false; 934 935 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))) { 936 var self = this; 937 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 938 if(self._trigger("stop", event) !== false) { 939 self._clear(); 940 } 941 }); 942 } else { 943 if(this._trigger("stop", event) !== false) { 944 this._clear(); 945 } 946 } 947 948 return false; 949 }, 950 951 _mouseUp: function(event) { 952 if (this.options.iframeFix === true) { 953 $("div.ui-draggable-iframeFix").each(function() { 954 this.parentNode.removeChild(this); 955 }); //Remove frame helpers 956 } 957 958 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 959 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); 960 961 return $.ui.mouse.prototype._mouseUp.call(this, event); 962 }, 963 964 cancel: function() { 965 966 if(this.helper.is(".ui-draggable-dragging")) { 967 this._mouseUp({}); 968 } else { 969 this._clear(); 970 } 971 972 return this; 973 974 }, 975 976 _getHandle: function(event) { 977 978 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; 979 $(this.options.handle, this.element) 980 .find("*") 981 .andSelf() 982 .each(function() { 983 if(this == event.target) handle = true; 984 }); 985 986 return handle; 987 988 }, 989 990 _createHelper: function(event) { 991 992 var o = this.options; 993 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); 994 995 if(!helper.parents('body').length) 996 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); 997 998 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) 999 helper.css("position", "absolute"); 1000 1001 return helper; 1002 1003 }, 1004 1005 _adjustOffsetFromHelper: function(obj) { 1006 if (typeof obj == 'string') { 1007 obj = obj.split(' '); 1008 } 1009 if ($.isArray(obj)) { 1010 obj = {left: +obj[0], top: +obj[1] || 0}; 1011 } 1012 if ('left' in obj) { 1013 this.offset.click.left = obj.left + this.margins.left; 1014 } 1015 if ('right' in obj) { 1016 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 1017 } 1018 if ('top' in obj) { 1019 this.offset.click.top = obj.top + this.margins.top; 1020 } 1021 if ('bottom' in obj) { 1022 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 1023 } 1024 }, 1025 1026 _getParentOffset: function() { 1027 1028 //Get the offsetParent and cache its position 1029 this.offsetParent = this.helper.offsetParent(); 1030 var po = this.offsetParent.offset(); 1031 1032 // This is a special case where we need to modify a offset calculated on start, since the following happened: 1033 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 1034 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 1035 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 1036 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { 1037 po.left += this.scrollParent.scrollLeft(); 1038 po.top += this.scrollParent.scrollTop(); 1039 } 1040 1041 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information 1042 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix 1043 po = { top: 0, left: 0 }; 1044 1045 return { 1046 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),
104610) || 0), 1047 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 1048 }; 1049 1050 }, 1051 1052 _getRelativeOffset: function() { 1053 1054 if(this.cssPosition == "relative") { 1055 var p = this.element.position(); 1056 return { 1057 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 1058 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 1059 }; 1060 } else { 1061 return { top: 0, left: 0 }; 1062 } 1063 1064 }, 1065 1066 _cacheMargins: function() { 1067 this.margins = { 1068 left: (parseInt(this.element.css("marginLeft"),10) || 0), 1069 top: (parseInt(this.element.css("marginTop"),10) || 0), 1070 right: (parseInt(this.element.css("marginRight"),10) || 0), 1071 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 1072 }; 1073 }, 1074 1075 _cacheHelperProportions: function() { 1076 this.helperProportions = { 1077 width: this.helper.outerWidth(), 1078 height: this.helper.outerHeight() 1079 }; 1080 }, 1081 1082 _setContainment: function() { 1083 1084 var o = this.options; 1085 if(o.containment == 'parent') o.containment = this.helper[0].parentNode; 1086 if(o.containment == 'document' || o.containment == 'window') this.containment = [ 1087 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 1088 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, 1089 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, 1090 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 1091 ]; 1092 1093 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { 1094 var c = $(o.containment); 1095 var ce = c[0]; if(!ce) return; 1096 var co = c.offset(); 1097 var over = ($(ce).css("overflow") != 'hidden'); 1098 1099 this.containment = [ 1100 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), 1101 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), 1102 (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, 1103 (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 1104 ]; 1105 this.relative_container = c; 1106 1107 } else if(o.containment.constructor == Array) { 1108 this.containment = o.containment; 1109 } 1110 1111 }, 1112 1113 _convertPositionTo: function(d, pos) { 1114 1115 if(!pos) pos = this.position; 1116 var mod = d == "absolute" ? 1 : -1; 1117 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); 1118 1119 return { 1120 top: ( 1121 pos.top // The absolute mouse position 1122 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent 1123 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) 1124 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 1125 ), 1126 left: ( 1127 pos.left // The absolute mouse position 1128 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent 1129 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) 1130 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 1131 ) 1132 }; 1133 1134 }, 1135 1136 _generatePosition: function(event) { 1137 1138 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); 1139 var pageX = event.pageX; 1140 var pageY = event.pageY; 1141 1142 /* 1143 * - Position constraining - 1144 * Constrain the position to a mix of grid, containment. 1145 */ 1146 1147 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 1148 var containment; 1149 if(this.containment) { 1150 if (this.relative_container){ 1151 var co = this.relative_container.offset(); 1152 containment = [ this.containment[0] + co.left, 1153 this.containment[1] + co.top, 1154 this.containment[2] + co.left, 1155 this.containment[3] + co.top ]; 1156 } 1157 else { 1158 containment = this.containment; 1159 } 1160 1161 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; 1162 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; 1163 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; 1164 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; 1165 } 1166 1167 if(o.grid) { 1168 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 1169 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 1170 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; 1171 1172 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 1173 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; 1174 } 1175 1176 } 1177 1178 return { 1179 top: ( 1180 pageY // The absolute mouse position 1181 - this.offset.click.top // Click offset (relative to the element) 1182 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent 1183 - this.offset.parent.top // The offsetParent's offset without borders (offset + border) 1184 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 1185 ), 1186 left: ( 1187 pageX // The absolute mouse position 1188 - this.offset.click.left // Click offset (relative to the element) 1189 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent 1190 - this.offset.parent.left // The offsetParent's offset without borders (offset + border) 1191 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 1192 ) 1193 }; 1194 1195 }, 1196 1197 _clear: function() { 1198 this.helper.removeClass("ui-draggable-dragging"); 1199 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); 1200 //if($.ui.ddmanager) $.ui.ddmanager.current = null; 1201 this.helper = null; 1202 this.cancelHelperRemoval = false; 1203 }, 1204 1205 // From now on bulk stuff - mainly helpers 1206 1207 _trigger: function(type, event, ui) { 1208 ui = ui || this._uiHash(); 1209 $.ui.plugin.call(this, type, [event, ui]); 1210 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins 1211 return $.Widget.prototype._trigger.call(this, type, event, ui); 1212 }, 1213 1214 plugins: {}, 1215 1216 _uiHash: function(event) { 1217 return { 1218 helper: this.helper, 1219 position: this.position, 1220 originalPosition: this.originalPosition, 1221 offset: this.positionAbs 1222 }; 1223 } 1224 1225}); 1226 1227$.extend($.ui.draggable, { 1228 version: "@VERSION" 1229}); 1230 1231$.ui.plugin.add("draggable", "connectToSortable", { 1232 start: function(event, ui) { 1233 1234 var inst = $(this).data("draggable"), o = inst.options, 1235 uiSortable = $.extend({}, ui, { item: inst.element }); 1236 inst.sortables = []; 1237 $(o.connectToSortable).each(function() { 1238 var sortable = $.data(this, 'sortable');
1239 if (sortable && !sortable.options.disabled) { 1240 inst.sortables.push({ 1241 instance: sortable, 1242 shouldRevert: sortable.options.revert 1243 }); 1244 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). 1245 sortable._trigger("activate", event, uiSortable); 1246 } 1247 }); 1248 1249 }, 1250 stop: function(event, ui) { 1251 1252 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 1253 var inst = $(this).data("draggable"), 1254 uiSortable = $.extend({}, ui, { item: inst.element }); 1255 1256 $.each(inst.sortables, function() { 1257 if(this.instance.isOver) { 1258 1259 this.instance.isOver = 0; 1260 1261 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 1262 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 1263 1264 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' 1265 if(this.shouldRevert) this.instance.options.revert = true; 1266 1267 //Trigger the stop of the sortable 1268 this.instance._mouseStop(event); 1269 1270 this.instance.options.helper = this.instance.options._helper; 1271 1272 //If the helper has been the original item, restore properties in the sortable 1273 if(inst.options.helper == 'original') 1274 this.instance.currentItem.css({ top: 'auto', left: 'auto' }); 1275 1276 } else { 1277 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 1278 this.instance._trigger("deactivate", event, uiSortable); 1279 } 1280 1281 }); 1282 1283 }, 1284 drag: function(event, ui) { 1285 1286 var inst = $(this).data("draggable"), self = this; 1287 1288 var checkPos = function(o) { 1289 var dyClick = this.offset.click.top, dxClick = this.offset.click.left; 1290 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; 1291 var itemHeight = o.height, itemWidth = o.width; 1292 var itemTop = o.top, itemLeft = o.left; 1293 1294 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); 1295 }; 1296 1297 $.each(inst.sortables, function(i) { 1298 1299 //Copy over some variables to allow calling the sortable's native _intersectsWith 1300 this.instance.positionAbs = inst.positionAbs; 1301 this.instance.helperProportions = inst.helperProportions; 1302 this.instance.offset.click = inst.offset.click; 1303 1304 if(this.instance._intersectsWith(this.instance.containerCache)) { 1305 1306 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 1307 if(!this.instance.isOver) { 1308 1309 this.instance.isOver = 1; 1310 //Now we fake the start of dragging for the sortable instance, 1311 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 1312 //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) 1313 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); 1314 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 1315 this.instance.options.helper = function() { return ui.helper[0]; }; 1316 1317 event.target = this.instance.currentItem[0]; 1318 this.instance._mouseCapture(event, true); 1319 this.instance._mouseStart(event, true, true); 1320 1321 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 1322 this.instance.offset.click.top = inst.offset.click.top; 1323 this.instance.offset.click.left = inst.offset.click.left; 1324 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 1325 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 1326 1327 inst._trigger("toSortable", event); 1328 inst.dropped = this.instance.element; //draggable revert needs that 1329 //hack so receive/update callbacks work (mostly) 1330 inst.currentItem = inst.element; 1331 this.instance.fromOutside = inst; 1332 1333 } 1334 1335 //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 1336 if(this.instance.currentItem) this.instance._mouseDrag(event); 1337 1338 } else { 1339 1340 //If it doesn't intersect with the sortable, and it intersected before, 1341 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 1342 if(this.instance.isOver) { 1343 1344 this.instance.isOver = 0; 1345 this.instance.cancelHelperRemoval = true; 1346 1347 //Prevent reverting on this forced stop 1348 this.instance.options.revert = false; 1349 1350 // The out event needs to be triggered independently 1351 this.instance._trigger('out', event, this.instance._uiHash(this.instance)); 1352 1353 this.instance._mouseStop(event, true); 1354 this.instance.options.helper = this.instance.options._helper; 1355 1356 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 1357 this.instance.currentItem.remove(); 1358 if(this.instance.placeholder) this.instance.placeholder.remove(); 1359 1360 inst._trigger("fromSortable", event); 1361 inst.dropped = false; //draggable revert needs that 1362 } 1363 1364 }; 1365 1366 }); 1367 1368 } 1369}); 1370 1371$.ui.plugin.add("draggable", "cursor", { 1372 start: function(event, ui) { 1373 var t = $('body'), o = $(this).data('draggable').options; 1374 if (t.css("cursor")) o._cursor = t.css("cursor"); 1375 t.css("cursor", o.cursor); 1376 }, 1377 stop: function(event, ui) { 1378 var o = $(this).data('draggable').options; 1379 if (o._cursor) $('body').css("cursor", o._cursor); 1380 } 1381}); 1382 1383$.ui.plugin.add("draggable", "opacity", { 1384 start: function(event, ui) { 1385 var t = $(ui.helper), o = $(this).data('draggable').options; 1386 if(t.css("opacity")) o._opacity = t.css("opacity"); 1387 t.css('opacity', o.opacity); 1388 }, 1389 stop: function(event, ui) { 1390 var o = $(this).data('draggable').options; 1391 if(o._opacity) $(ui.helper).css('opacity', o._opacity); 1392 } 1393}); 1394 1395$.ui.plugin.add("draggable", "scroll", { 1396 start: function(event, ui) { 1397 var i = $(this).data("draggable"); 1398 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); 1399 }, 1400 drag: function(event, ui) { 1401 1402 var i = $(this).data("draggable"), o = i.options, scrolled = false; 1403 1404 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { 1405 1406 if(!o.axis || o.axis != 'x') { 1407 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) 1408 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 1409 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) 1410 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 1411 } 1412 1413 if(!o.axis || o.axis != 'y') { 1414 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) 1415 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 1416 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) 1417 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 1418 } 1419 1420 } else { 1421 1422 if(!o.axis || o.axis != 'x') { 1423 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) 1424 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 1425 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) 1426 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 1427 } 1428 1429 if(!o.axis || o.axis != 'y') { 1430 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) 1431 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 1432 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) 1433 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 1434 } 1435 1436 } 1437 1438 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) 1439 $.ui.ddmanager.prepareOffsets(i, event); 1440 1441 } 1442}); 1443 1444$.ui.plugin.add("draggable", "snap", { 1445 start: function(event, ui) { 1446 1447 var i = $(this).data("draggable"), o = i.options; 1448 i.snapElements = []; 1449 1450 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { 1451 var $t = $(this); var $o = $t.offset(); 1452 if(this != i.element[0]) i.snapElements.push({ 1453 item: this, 1454 width: $t.outerWidth(), height: $t.outerHeight(), 1455 top: $o.top, left: $o.left 1456 }); 1457 }); 1458 1459 }, 1460 drag: function(event, ui) { 1461 1462 var inst = $(this).data("draggable"), o = inst.options; 1463 var d = o.snapTolerance; 1464 1465 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 1466 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 1467 1468 for (var i = inst.snapElements.length - 1; i >= 0; i--){ 1469 1470 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, 1471 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; 1472 1473 //Yes, I know, this is insane ;) 1474 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))) { 1475 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 }))); 1476 inst.snapElements[i].snapping = false; 1477 continue; 1478 } 1479 1480 if(o.snapMode != 'inner') { 1481 var ts = Math.abs(t - y2) <= d; 1482 var bs = Math.abs(b - y1) <= d; 1483 var ls = Math.abs(l - x2) <= d; 1484 var rs = Math.abs(r - x1) <= d; 1485 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 1486 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 1487 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 1488 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 1489 } 1490 1491 var first = (ts || bs || ls || rs); 1492 1493 if(o.snapMode != 'outer') { 1494 var ts = Math.abs(t - y1) <= d; 1495 var bs = Math.abs(b - y2) <= d; 1496 var ls = Math.abs(l - x1) <= d; 1497 var rs = Math.abs(r - x2) <= d; 1498 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 1499 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 1500 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 1501 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 1502 } 1503 1504 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) 1505 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 1506 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 1507 1508 }; 1509 1510 } 1511}); 1512 1513$.ui.plugin.add("draggable", "stack", { 1514 start: function(event, ui) { 1515 1516 var o = $(this).data("draggable").options; 1517 1518 var group = $.makeArray($(o.stack)).sort(function(a,b) { 1519 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 1520 }); 1521 if (!group.length) { return; } 1522 1523 var min = parseInt(group[0].style.zIndex) || 0; 1524 $(group).each(function(i) { 1525 this.style.zIndex = min + i; 1526 }); 1527 1528 this[0].style.zIndex = min + group.length; 1529 1530 } 1531}); 1532 1533$.ui.plugin.add("draggable", "zIndex", { 1534 start: function(event, ui) { 1535 var t = $(ui.helper), o = $(this).data("draggable").options; 1536 if(t.css("zIndex")) o._zIndex = t.css("zIndex"); 1537 t.css('zIndex', o.zIndex); 1538 }, 1539 stop: function(event, ui) { 1540 var o = $(this).data("draggable").options; 1541 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); 1542 } 1543}); 1544 1545})(jQuery); 1546 1547(function( $, undefined ) { 1548 1549$.widget("ui.droppable", { 1550 widgetEventPrefix: "drop", 1551 options: { 1552 accept: '*',
1553 activeClass: false, 1554 addClasses: true, 1555 greedy: false, 1556 hoverClass: false, 1557 scope: 'default', 1558 tolerance: 'intersect' 1559 }, 1560 _create: function() { 1561 1562 var o = this.options, accept = o.accept; 1563 this.isover = 0; this.isout = 1; 1564 1565 this.accept = $.isFunction(accept) ? accept : function(d) { 1566 return d.is(accept); 1567 }; 1568 1569 //Store the droppable's proportions 1570 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; 1571 1572 // Add the reference and positions to the manager 1573 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 1574 $.ui.ddmanager.droppables[o.scope].push(this); 1575 1576 (o.addClasses && this.element.addClass("ui-droppable")); 1577 1578 }, 1579 1580 destroy: function() { 1581 var drop = $.ui.ddmanager.droppables[this.options.scope]; 1582 for ( var i = 0; i < drop.length; i++ ) 1583 if ( drop[i] == this ) 1584 drop.splice(i, 1); 1585 1586 this.element 1587 .removeClass("ui-droppable ui-droppable-disabled") 1588 .removeData("droppable") 1589 .unbind(".droppable"); 1590 1591 return this; 1592 }, 1593 1594 _setOption: function(key, value) { 1595 1596 if(key == 'accept') { 1597 this.accept = $.isFunction(value) ? value : function(d) { 1598 return d.is(value); 1599 }; 1600 } 1601 $.Widget.prototype._setOption.apply(this, arguments); 1602 }, 1603 1604 _activate: function(event) { 1605 var draggable = $.ui.ddmanager.current; 1606 if(this.options.activeClass) this.element.addClass(this.options.activeClass); 1607 (draggable && this._trigger('activate', event, this.ui(draggable))); 1608 }, 1609 1610 _deactivate: function(event) { 1611 var draggable = $.ui.ddmanager.current; 1612 if(this.options.activeClass) this.element.removeClass(this.options.activeClass); 1613 (draggable && this._trigger('deactivate', event, this.ui(draggable))); 1614 }, 1615 1616 _over: function(event) { 1617 1618 var draggable = $.ui.ddmanager.current; 1619 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element 1620 1621 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1622 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); 1623 this._trigger('over', event, this.ui(draggable)); 1624 } 1625 1626 }, 1627 1628 _out: function(event) { 1629 1630 var draggable = $.ui.ddmanager.current; 1631 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element 1632 1633 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1634 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); 1635 this._trigger('out', event, this.ui(draggable)); 1636 } 1637 1638 }, 1639 1640 _drop: function(event,custom) { 1641 1642 var draggable = custom || $.ui.ddmanager.current; 1643 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element 1644 1645 var childrenIntersection = false; 1646 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { 1647 var inst = $.data(this, 'droppable'); 1648 if( 1649 inst.options.greedy 1650 && !inst.options.disabled 1651 && inst.options.scope == draggable.options.scope 1652 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) 1653 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 1654 ) { childrenIntersection = true; return false; } 1655 }); 1656 if(childrenIntersection) return false; 1657 1658 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1659 if(this.options.activeClass) this.element.removeClass(this.options.activeClass); 1660 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); 1661 this._trigger('drop', event, this.ui(draggable)); 1662 return this.element; 1663 } 1664 1665 return false; 1666 1667 }, 1668 1669 ui: function(c) { 1670 return { 1671 draggable: (c.currentItem || c.element), 1672 helper: c.helper, 1673 position: c.position, 1674 offset: c.positionAbs 1675 }; 1676 } 1677 1678}); 1679 1680$.extend($.ui.droppable, { 1681 version: "@VERSION" 1682}); 1683 1684$.ui.intersect = function(draggable, droppable, toleranceMode) { 1685 1686 if (!droppable.offset) return false; 1687 1688 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 1689 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; 1690 var l = droppable.offset.left, r = l + droppable.proportions.width, 1691 t = droppable.offset.top, b = t + droppable.proportions.height; 1692 1693 switch (toleranceMode) { 1694 case 'fit': 1695 return (l <= x1 && x2 <= r 1696 && t <= y1 && y2 <= b); 1697 break; 1698 case 'intersect': 1699 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half 1700 && x2 - (draggable.helperProportions.width / 2) < r // Left Half 1701 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half 1702 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 1703 break; 1704 case 'pointer': 1705 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), 1706 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), 1707 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); 1708 return isOver; 1709 break; 1710 case 'touch': 1711 return ( 1712 (y1 >= t && y1 <= b) || // Top edge touching 1713 (y2 >= t && y2 <= b) || // Bottom edge touching 1714 (y1 < t && y2 > b) // Surrounded vertically 1715 ) && ( 1716 (x1 >= l && x1 <= r) || // Left edge touching 1717 (x2 >= l && x2 <= r) || // Right edge touching 1718 (x1 < l && x2 > r) // Surrounded horizontally 1719 ); 1720 break; 1721 default: 1722 return false; 1723 break; 1724 } 1725 1726}; 1727 1728/* 1729 This manager tracks offsets of draggables and droppables 1730*/ 1731$.ui.ddmanager = { 1732 current: null, 1733 droppables: { 'default': [] }, 1734 prepareOffsets: function(t, event) { 1735 1736 var m = $.ui.ddmanager.droppables[t.options.scope] || []; 1737 var type = event ? event.type : null; // workaround for #2317 1738 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); 1739 1740 droppablesLoop: for (var i = 0; i < m.length; i++) { 1741 1742 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted 1743 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 1744 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue 1745 1746 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables 1747 1748 m[i].offset = m[i].element.offset(); 1749 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; 1750 1751 } 1752 1753 }, 1754 drop: function(draggable, event) { 1755 1756 var dropped = false;
1757 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 1758 1759 if(!this.options) return; 1760 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) 1761 dropped = this._drop.call(this, event) || dropped; 1762 1763 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1764 this.isout = 1; this.isover = 0; 1765 this._deactivate.call(this, event); 1766 } 1767 1768 }); 1769 return dropped; 1770 1771 }, 1772 dragStart: function( draggable, event ) { 1773 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 1774 draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { 1775 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); 1776 }); 1777 }, 1778 drag: function(draggable, event) { 1779 1780 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 1781 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); 1782 1783 //Run through all droppables and check their positions based on specific tolerance options 1784 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 1785 1786 if(this.options.disabled || this.greedyChild || !this.visible) return; 1787 var intersects = $.ui.intersect(draggable, this, this.options.tolerance); 1788 1789 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); 1790 if(!c) return; 1791 1792 var parentInstance; 1793 if (this.options.greedy) { 1794 var parent = this.element.parents(':data(droppable):eq(0)'); 1795 if (parent.length) { 1796 parentInstance = $.data(parent[0], 'droppable'); 1797 parentInstance.greedyChild = (c == 'isover' ? 1 : 0); 1798 } 1799 } 1800 1801 // we just moved into a greedy child 1802 if (parentInstance && c == 'isover') { 1803 parentInstance['isover'] = 0; 1804 parentInstance['isout'] = 1; 1805 parentInstance._out.call(parentInstance, event); 1806 } 1807 1808 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; 1809 this[c == "isover" ? "_over" : "_out"].call(this, event); 1810 1811 // we just moved out of a greedy child 1812 if (parentInstance && c == 'isout') { 1813 parentInstance['isout'] = 0; 1814 parentInstance['isover'] = 1; 1815 parentInstance._over.call(parentInstance, event); 1816 } 1817 }); 1818 1819 }, 1820 dragStop: function( draggable, event ) { 1821 draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); 1822 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 1823 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); 1824 } 1825}; 1826 1827})(jQuery); 1828 1829(function( $, undefined ) { 1830 1831$.widget("ui.resizable", $.ui.mouse, { 1832 widgetEventPrefix: "resize", 1833 options: { 1834 alsoResize: false, 1835 animate: false, 1836 animateDuration: "slow", 1837 animateEasing: "swing", 1838 aspectRatio: false, 1839 autoHide: false, 1840 containment: false, 1841 ghost: false, 1842 grid: false, 1843 handles: "e,s,se", 1844 helper: false, 1845 maxHeight: null, 1846 maxWidth: null, 1847 minHeight: 10, 1848 minWidth: 10, 1849 zIndex: 1000 1850 }, 1851 _create: function() { 1852 1853 var self = this, o = this.options; 1854 this.element.addClass("ui-resizable"); 1855 1856 $.extend(this, { 1857 _aspectRatio: !!(o.aspectRatio), 1858 aspectRatio: o.aspectRatio, 1859 originalElement: this.element, 1860 _proportionallyResizeElements: [], 1861 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null 1862 }); 1863 1864 //Wrap the element if it cannot hold child nodes 1865 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 1866 1867 //Create a wrapper element and set the wrapper to the new current internal element 1868 this.element.wrap( 1869 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({ 1870 position: this.element.css('position'), 1871 width: this.element.outerWidth(), 1872 height: this.element.outerHeight(), 1873 top: this.element.css('top'), 1874 left: this.element.css('left') 1875 }) 1876 ); 1877 1878 //Overwrite the original this.element 1879 this.element = this.element.parent().data( 1880 "resizable", this.element.data('resizable') 1881 ); 1882 1883 this.elementIsWrapper = true; 1884 1885 //Move margins to the wrapper 1886 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 1887 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 1888 1889 //Prevent Safari textarea resize 1890 this.originalResizeStyle = this.originalElement.css('resize'); 1891 this.originalElement.css('resize', 'none'); 1892 1893 //Push the actual element to our proportionallyResize internal array 1894 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); 1895 1896 // avoid IE jump (hard set the margin) 1897 this.originalElement.css({ margin: this.originalElement.css('margin') }); 1898 1899 // fix handlers offset 1900 this._proportionallyResize(); 1901 1902 } 1903 1904 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' });
1905 if(this.handles.constructor == String) { 1906 1907 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; 1908 var n = this.handles.split(","); this.handles = {}; 1909 1910 for(var i = 0; i < n.length; i++) { 1911 1912 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; 1913 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>'); 1914 1915 // increase zIndex of sw, se, ne, nw axis 1916 //TODO : this modifies original option 1917 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); 1918 1919 //TODO : What's going on here? 1920 if ('se' == handle) { 1921 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); 1922 }; 1923 1924 //Insert into internal handles object and append to element 1925 this.handles[handle] = '.ui-resizable-'+handle; 1926 this.element.append(axis); 1927 } 1928 1929 } 1930 1931 this._renderAxis = function(target) { 1932 1933 target = target || this.element; 1934 1935 for(var i in this.handles) { 1936 1937 if(this.handles[i].constructor == String) 1938 this.handles[i] = $(this.handles[i], this.element).show(); 1939 1940 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 1941 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 1942 1943 var axis = $(this.handles[i], this.element), padWrapper = 0; 1944 1945 //Checking the correct pad and border 1946 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 1947 1948 //The padding type i have to apply... 1949 var padPos = [ 'padding', 1950 /ne|nw|n/.test(i) ? 'Top' : 1951 /se|sw|s/.test(i) ? 'Bottom' : 1952 /^e$/.test(i) ? 'Right' : 'Left' ].join(""); 1953 1954 target.css(padPos, padWrapper); 1955 1956 this._proportionallyResize(); 1957 1958 } 1959 1960 //TODO: What's that good for? There's not anything to be executed left 1961 if(!$(this.handles[i]).length) 1962 continue; 1963 1964 } 1965 }; 1966 1967 //TODO: make renderAxis a prototype function 1968 this._renderAxis(this.element); 1969 1970 this._handles = $('.ui-resizable-handle', this.element) 1971 .disableSelection(); 1972 1973 //Matching axis name 1974 this._handles.mouseover(function() { 1975 if (!self.resizing) { 1976 if (this.className) 1977 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 1978 //Axis, default = se 1979 self.axis = axis && axis[1] ? axis[1] : 'se'; 1980 } 1981 }); 1982 1983 //If we want to auto hide the elements 1984 if (o.autoHide) { 1985 this._handles.hide(); 1986 $(this.element) 1987 .addClass("ui-resizable-autohide") 1988 .hover(function() { 1989 if (o.disabled) return; 1990 $(this).removeClass("ui-resizable-autohide"); 1991 self._handles.show(); 1992 }, 1993 function(){ 1994 if (o.disabled) return; 1995 if (!self.resizing) { 1996 $(this).addClass("ui-resizable-autohide"); 1997 self._handles.hide(); 1998 } 1999 }); 2000 } 2001 2002 //Initialize the mouse interaction 2003 this._mouseInit(); 2004 2005 }, 2006 2007 destroy: function() { 2008 2009 this._mouseDestroy(); 2010 2011 var _destroy = function(exp) { 2012 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 2013 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); 2014 }; 2015 2016 //TODO: Unwrap at same DOM position 2017 if (this.elementIsWrapper) { 2018 _destroy(this.element); 2019 var wrapper = this.element; 2020 wrapper.after( 2021 this.originalElement.css({ 2022 position: wrapper.css('position'), 2023 width: wrapper.outerWidth(), 2024 height: wrapper.outerHeight(), 2025 top: wrapper.css('top'), 2026 left: wrapper.css('left') 2027 }) 2028 ).remove(); 2029 } 2030 2031 this.originalElement.css('resize', this.originalResizeStyle); 2032 _destroy(this.originalElement); 2033 2034 return this; 2035 }, 2036 2037 _mouseCapture: function(event) { 2038 var handle = false; 2039 for (var i in this.handles) { 2040 if ($(this.handles[i])[0] == event.target) { 2041 handle = true; 2042 } 2043 } 2044 2045 return !this.options.disabled && handle; 2046 }, 2047 2048 _mouseStart: function(event) { 2049 2050 var o = this.options, iniPos = this.element.position(), el = this.element; 2051 2052 this.resizing = true; 2053 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; 2054 2055 // bugfix for http://dev.jquery.com/ticket/1749 2056 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { 2057 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); 2058 } 2059 2060 this._renderProxy(); 2061 2062 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); 2063 2064 if (o.containment) { 2065 curleft += $(o.containment).scrollLeft() || 0; 2066 curtop += $(o.containment).scrollTop() || 0; 2067 } 2068 2069 //Store needed variables 2070 this.offset = this.helper.offset(); 2071 this.position = { left: curleft, top: curtop }; 2072 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 2073 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 2074 this.originalPosition = { left: curleft, top: curtop }; 2075 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 2076 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 2077 2078 //Aspect Ratio 2079 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 2080 2081 var cursor = $('.ui-resizable-' + this.axis).css('cursor'); 2082 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); 2083 2084 el.addClass("ui-resizable-resizing"); 2085 this._propagate("start", event); 2086 return true; 2087 }, 2088 2089 _mouseDrag: function(event) { 2090 2091 //Increase performance, avoid regex 2092 var el = this.helper, o = this.options, props = {}, 2093 self = this, smp = this.originalMousePosition, a = this.axis; 2094 2095 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; 2096 var trigger = this._change[a]; 2097 if (!trigger) return false; 2098 2099 // Calculate the attrs that will be change 2100 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; 2101 2102 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 2103 this._updateVirtualBoundaries(event.shiftKey); 2104 if (this._aspectRatio || event.shiftKey) 2105 data = this._updateRatio(data, event); 2106 2107 data = this._respectSize(data, event); 2108 2109 // plugins callbacks need to be called first 2110 this._propagate("resize", event); 2111 2112 el.css({ 2113 top: this.position.top + "px", left: this.position.left + "px", 2114 width: this.size.width + "px", height: this.size.height + "px" 2115 }); 2116 2117 if (!this._helper && this._proportionallyResizeElements.length) 2118 this._proportionallyResize(); 2119 2120 this._updateCache(data); 2121 2122 // calling the user callback at the end 2123 this._trigger('resize', event, this.ui()); 2124 2125 return false; 2126 }, 2127 2128 _mouseStop: function(event) { 2129 2130 this.resizing = false; 2131 var o = this.options, self = this; 2132 2133 if(this._helper) { 2134 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), 2135 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, 2136 soffsetw = ista ? 0 : self.sizeDiff.width; 2137 2138 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) }, 2139 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, 2140 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; 2141 2142 if (!o.animate) 2143 this.element.css($.extend(s, { top: top, left: left })); 2144 2145 self.helper.height(self.size.height); 2146 self.helper.width(self.size.width); 2147
2148 if (this._helper && !o.animate) this._proportionallyResize(); 2149 } 2150 2151 $('body').css('cursor', 'auto'); 2152 2153 this.element.removeClass("ui-resizable-resizing"); 2154 2155 this._propagate("stop", event); 2156 2157 if (this._helper) this.helper.remove(); 2158 return false; 2159 2160 }, 2161 2162 _updateVirtualBoundaries: function(forceAspectRatio) { 2163 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; 2164 2165 b = { 2166 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 2167 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 2168 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 2169 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 2170 }; 2171 2172 if(this._aspectRatio || forceAspectRatio) { 2173 // We want to create an enclosing box whose aspect ration is the requested one 2174 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 2175 pMinWidth = b.minHeight * this.aspectRatio; 2176 pMinHeight = b.minWidth / this.aspectRatio; 2177 pMaxWidth = b.maxHeight * this.aspectRatio; 2178 pMaxHeight = b.maxWidth / this.aspectRatio; 2179 2180 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; 2181 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; 2182 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; 2183 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; 2184 } 2185 this._vBoundaries = b; 2186 }, 2187 2188 _updateCache: function(data) { 2189 var o = this.options; 2190 this.offset = this.helper.offset(); 2191 if (isNumber(data.left)) this.position.left = data.left; 2192 if (isNumber(data.top)) this.position.top = data.top; 2193 if (isNumber(data.height)) this.size.height = data.height; 2194 if (isNumber(data.width)) this.size.width = data.width; 2195 }, 2196 2197 _updateRatio: function(data, event) { 2198 2199 var o = this.options, cpos = this.position, csize = this.size, a = this.axis; 2200 2201 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); 2202 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); 2203 2204 if (a == 'sw') { 2205 data.left = cpos.left + (csize.width - data.width); 2206 data.top = null; 2207 } 2208 if (a == 'nw') { 2209 data.top = cpos.top + (csize.height - data.height); 2210 data.left = cpos.left + (csize.width - data.width); 2211 } 2212 2213 return data; 2214 }, 2215 2216 _respectSize: function(data, event) { 2217 2218 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, 2219 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 2220 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); 2221 2222 if (isminw) data.width = o.minWidth; 2223 if (isminh) data.height = o.minHeight; 2224 if (ismaxw) data.width = o.maxWidth; 2225 if (ismaxh) data.height = o.maxHeight; 2226 2227 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; 2228 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 2229 2230 if (isminw && cw) data.left = dw - o.minWidth; 2231 if (ismaxw && cw) data.left = dw - o.maxWidth; 2232 if (isminh && ch) data.top = dh - o.minHeight; 2233 if (ismaxh && ch) data.top = dh - o.maxHeight; 2234 2235 // fixing jump error on top/left - bug #2330 2236 var isNotwh = !data.width && !data.height; 2237 if (isNotwh && !data.left && data.top) data.top = null; 2238 else if (isNotwh && !data.top && data.left) data.left = null; 2239 2240 return data; 2241 }, 2242 2243 _proportionallyResize: function() { 2244 2245 var o = this.options; 2246 if (!this._proportionallyResizeElements.length) return; 2247 var element = this.helper || this.element; 2248 2249 for (var i=0; i < this._proportionallyResizeElements.length; i++) { 2250 2251 var prel = this._proportionallyResizeElements[i]; 2252 2253 if (!this.borderDif) { 2254 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], 2255 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; 2256 2257 this.borderDif = $.map(b, function(v, i) { 2258 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; 2259 return border + padding; 2260 }); 2261 } 2262 2263 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) 2264 continue; 2265 2266 prel.css({ 2267 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 2268 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 2269 }); 2270 2271 }; 2272 2273 }, 2274 2275 _renderProxy: function() { 2276 2277 var el = this.element, o = this.options; 2278 this.elementOffset = el.offset(); 2279 2280 if(this._helper) { 2281 2282 this.helper = this.helper || $('<div style="overflow:hidden;"></div>'); 2283 2284 // fix ie6 offset TODO: This seems broken 2285 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), 2286 pxyoffset = ( ie6 ? 2 : -1 ); 2287 2288 this.helper.addClass(this._helper).css({ 2289 width: this.element.outerWidth() + pxyoffset, 2290 height: this.element.outerHeight() + pxyoffset, 2291 position: 'absolute', 2292 left: this.elementOffset.left - ie6offset +'px', 2293 top: this.elementOffset.top - ie6offset +'px', 2294 zIndex: ++o.zIndex //TODO: Don't modify option 2295 }); 2296 2297 this.helper 2298 .appendTo("body") 2299 .disableSelection(); 2300 2301 } else { 2302 this.helper = this.element; 2303 } 2304 2305 }, 2306 2307 _change: { 2308 e: function(event, dx, dy) { 2309 return { width: this.originalSize.width + dx }; 2310 }, 2311 w: function(event, dx, dy) { 2312 var o = this.options, cs = this.originalSize, sp = this.originalPosition; 2313 return { left: sp.left + dx, width: cs.width - dx }; 2314 }, 2315 n: function(event, dx, dy) { 2316 var o = this.options, cs = this.originalSize, sp = this.originalPosition; 2317 return { top: sp.top + dy, height: cs.height - dy }; 2318 }, 2319 s: function(event, dx, dy) { 2320 return { height: this.originalSize.height + dy }; 2321 }, 2322 se: function(event, dx, dy) { 2323 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 2324 }, 2325 sw: function(event, dx, dy) { 2326 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 2327 }, 2328 ne: function(event, dx, dy) { 2329 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 2330 }, 2331 nw: function(event, dx, dy) { 2332 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 2333 } 2334 }, 2335
2336 _propagate: function(n, event) { 2337 $.ui.plugin.call(this, n, [event, this.ui()]); 2338 (n != "resize" && this._trigger(n, event, this.ui())); 2339 }, 2340 2341 plugins: {}, 2342 2343 ui: function() { 2344 return { 2345 originalElement: this.originalElement, 2346 element: this.element, 2347 helper: this.helper, 2348 position: this.position, 2349 size: this.size, 2350 originalSize: this.originalSize, 2351 originalPosition: this.originalPosition 2352 }; 2353 } 2354 2355}); 2356 2357$.extend($.ui.resizable, { 2358 version: "@VERSION" 2359}); 2360 2361/* 2362 * Resizable Extensions 2363 */ 2364 2365$.ui.plugin.add("resizable", "alsoResize", { 2366 2367 start: function (event, ui) { 2368 var self = $(this).data("resizable"), o = self.options; 2369 2370 var _store = function (exp) { 2371 $(exp).each(function() { 2372 var el = $(this); 2373 el.data("resizable-alsoresize", { 2374 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 2375 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) 2376 }); 2377 }); 2378 }; 2379 2380 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { 2381 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 2382 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 2383 }else{ 2384 _store(o.alsoResize); 2385 } 2386 }, 2387 2388 resize: function (event, ui) { 2389 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; 2390 2391 var delta = { 2392 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, 2393 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 2394 }, 2395 2396 _alsoResize = function (exp, c) { 2397 $(exp).each(function() { 2398 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 2399 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; 2400 2401 $.each(css, function (i, prop) { 2402 var sum = (start[prop]||0) + (delta[prop]||0); 2403 if (sum && sum >= 0) 2404 style[prop] = sum || null; 2405 }); 2406 2407 el.css(style); 2408 }); 2409 }; 2410 2411 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { 2412 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 2413 }else{ 2414 _alsoResize(o.alsoResize); 2415 } 2416 }, 2417 2418 stop: function (event, ui) { 2419 $(this).removeData("resizable-alsoresize"); 2420 } 2421}); 2422 2423$.ui.plugin.add("resizable", "animate", { 2424 2425 stop: function(event, ui) { 2426 var self = $(this).data("resizable"), o = self.options; 2427 2428 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), 2429 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, 2430 soffsetw = ista ? 0 : self.sizeDiff.width; 2431 2432 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, 2433 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, 2434 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; 2435 2436 self.element.animate( 2437 $.extend(style, top && left ? { top: top, left: left } : {}), { 2438 duration: o.animateDuration, 2439 easing: o.animateEasing, 2440 step: function() { 2441 2442 var data = { 2443 width: parseInt(self.element.css('width'), 10), 2444 height: parseInt(self.element.css('height'), 10), 2445 top: parseInt(self.element.css('top'), 10), 2446 left: parseInt(self.element.css('left'), 10) 2447 }; 2448 2449 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); 2450 2451 // propagating resize, and updating values for each animation step 2452 self._updateCache(data); 2453 self._propagate("resize", event); 2454 2455 } 2456 } 2457 ); 2458 } 2459 2460}); 2461 2462$.ui.plugin.add("resizable", "containment", { 2463 2464 start: function(event, ui) { 2465 var self = $(this).data("resizable"), o = self.options, el = self.element; 2466 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 2467 if (!ce) return; 2468 2469 self.containerElement = $(ce); 2470 2471 if (/document/.test(oc) || oc == document) { 2472 self.containerOffset = { left: 0, top: 0 }; 2473 self.containerPosition = { left: 0, top: 0 }; 2474 2475 self.parentData = {
2476 element: $(document), left: 0, top: 0, 2477 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 2478 }; 2479 } 2480 2481 // i'm a node, so compute top, left, right, bottom 2482 else { 2483 var element = $(ce), p = []; 2484 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 2485 2486 self.containerOffset = element.offset(); 2487 self.containerPosition = element.position(); 2488 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 2489 2490 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, 2491 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 2492 2493 self.parentData = { 2494 element: ce, left: co.left, top: co.top, width: width, height: height 2495 }; 2496 } 2497 }, 2498 2499 resize: function(event, ui) { 2500 var self = $(this).data("resizable"), o = self.options, 2501 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, 2502 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; 2503 2504 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; 2505 2506 if (cp.left < (self._helper ? co.left : 0)) { 2507 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); 2508 if (pRatio) self.size.height = self.size.width / self.aspectRatio; 2509 self.position.left = o.helper ? co.left : 0; 2510 } 2511 2512 if (cp.top < (self._helper ? co.top : 0)) { 2513 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); 2514 if (pRatio) self.size.width = self.size.height * self.aspectRatio; 2515 self.position.top = self._helper ? co.top : 0; 2516 } 2517 2518 self.offset.left = self.parentData.left+self.position.left; 2519 self.offset.top = self.parentData.top+self.position.top; 2520 2521 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), 2522 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); 2523 2524 var isParent = self.containerElement.get(0) == self.element.parent().get(0), 2525 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); 2526 2527 if(isParent && isOffsetRelative) woset -= self.parentData.left; 2528 2529 if (woset + self.size.width >= self.parentData.width) { 2530 self.size.width = self.parentData.width - woset; 2531 if (pRatio) self.size.height = self.size.width / self.aspectRatio; 2532 } 2533 2534 if (hoset + self.size.height >= self.parentData.height) { 2535 self.size.height = self.parentData.height - hoset; 2536 if (pRatio) self.size.width = self.size.height * self.aspectRatio; 2537 } 2538 }, 2539 2540 stop: function(event, ui){ 2541 var self = $(this).data("resizable"), o = self.options, cp = self.position, 2542 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; 2543 2544 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; 2545 2546 if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) 2547 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 2548 2549 if (self._helper && !o.animate && (/static/).test(ce.css('position'))) 2550 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 2551 2552 } 2553}); 2554 2555$.ui.plugin.add("resizable", "ghost", { 2556 2557 start: function(event, ui) { 2558 2559 var self = $(this).data("resizable"), o = self.options, cs = self.size; 2560 2561 self.ghost = self.originalElement.clone(); 2562 self.ghost 2563 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 2564 .addClass('ui-resizable-ghost') 2565 .addClass(typeof o.ghost == 'string' ? o.ghost : ''); 2566 2567 self.ghost.appendTo(self.helper); 2568 2569 }, 2570 2571 resize: function(event, ui){ 2572 var self = $(this).data("resizable"), o = self.options; 2573 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); 2574 }, 2575 2576 stop: function(event, ui){ 2577 var self = $(this).data("resizable"), o = self.options; 2578 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); 2579 } 2580 2581}); 2582 2583$.ui.plugin.add("resizable", "grid", { 2584 2585 resize: function(event, ui) { 2586 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; 2587 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; 2588 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); 2589 2590 if (/^(se|s|e)$/.test(a)) { 2591 self.size.width = os.width + ox; 2592 self.size.height = os.height + oy; 2593 } 2594 else if (/^(ne)$/.test(a)) { 2595 self.size.width = os.width + ox; 2596 self.size.height = os.height + oy; 2597 self.position.top = op.top - oy; 2598 } 2599 else if (/^(sw)$/.test(a)) { 2600 self.size.width = os.width + ox; 2601 self.size.height = os.height + oy; 2602 self.position.left = op.left - ox; 2603 } 2604 else { 2605 self.size.width = os.width + ox; 2606 self.size.height = os.height + oy; 2607 self.position.top = op.top - oy; 2608 self.position.left = op.left - ox; 2609 } 2610 } 2611 2612}); 2613 2614var num = function(v) { 2615 return parseInt(v, 10) || 0; 2616}; 2617 2618var isNumber = function(value) { 2619 return !isNaN(parseInt(value, 10)); 2620}; 2621 2622})(jQuery); 2623 2624(function( $, undefined ) { 2625 2626$.widget("ui.selectable", $.ui.mouse, { 2627 options: { 2628 appendTo: 'body', 2629 autoRefresh: true, 2630 distance: 0, 2631 filter: '*', 2632 tolerance: 'touch' 2633 }, 2634 _create: function() { 2635 var self = this; 2636 2637 this.element.addClass("ui-selectable"); 2638 2639 this.dragged = false; 2640 2641 // cache selectee children based on filter 2642 var selectees;
2643 this.refresh = function() { 2644 selectees = $(self.options.filter, self.element[0]); 2645 selectees.addClass("ui-selectee"); 2646 selectees.each(function() { 2647 var $this = $(this); 2648 var pos = $this.offset(); 2649 $.data(this, "selectable-item", { 2650 element: this, 2651 $element: $this, 2652 left: pos.left, 2653 top: pos.top, 2654 right: pos.left + $this.outerWidth(), 2655 bottom: pos.top + $this.outerHeight(), 2656 startselected: false, 2657 selected: $this.hasClass('ui-selected'), 2658 selecting: $this.hasClass('ui-selecting'), 2659 unselecting: $this.hasClass('ui-unselecting') 2660 }); 2661 }); 2662 }; 2663 this.refresh(); 2664 2665 this.selectees = selectees.addClass("ui-selectee"); 2666 2667 this._mouseInit(); 2668 2669 this.helper = $("<div class='ui-selectable-helper'></div>"); 2670 }, 2671 2672 destroy: function() { 2673 this.selectees 2674 .removeClass("ui-selectee") 2675 .removeData("selectable-item"); 2676 this.element 2677 .removeClass("ui-selectable ui-selectable-disabled") 2678 .removeData("selectable") 2679 .unbind(".selectable"); 2680 this._mouseDestroy(); 2681 2682 return this; 2683 }, 2684 2685 _mouseStart: function(event) { 2686 var self = this; 2687 2688 this.opos = [event.pageX, event.pageY]; 2689 2690 if (this.options.disabled) 2691 return; 2692 2693 var options = this.options; 2694 2695 this.selectees = $(options.filter, this.element[0]); 2696 2697 this._trigger("start", event); 2698 2699 $(options.appendTo).append(this.helper); 2700 // position helper (lasso) 2701 this.helper.css({ 2702 "left": event.clientX, 2703 "top": event.clientY, 2704 "width": 0, 2705 "height": 0 2706 }); 2707 2708 if (options.autoRefresh) { 2709 this.refresh(); 2710 } 2711 2712 this.selectees.filter('.ui-selected').each(function() { 2713 var selectee = $.data(this, "selectable-item"); 2714 selectee.startselected = true; 2715 if (!event.metaKey && !event.ctrlKey) { 2716 selectee.$element.removeClass('ui-selected'); 2717 selectee.selected = false; 2718 selectee.$element.addClass('ui-unselecting'); 2719 selectee.unselecting = true; 2720 // selectable UNSELECTING callback 2721 self._trigger("unselecting", event, { 2722 unselecting: selectee.element 2723 }); 2724 } 2725 }); 2726 2727 $(event.target).parents().andSelf().each(function() { 2728 var selectee = $.data(this, "selectable-item"); 2729 if (selectee) { 2730 var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected'); 2731 selectee.$element 2732 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 2733 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 2734 selectee.unselecting = !doSelect; 2735 selectee.selecting = doSelect; 2736 selectee.selected = doSelect; 2737 // selectable (UN)SELECTING callback 2738 if (doSelect) { 2739 self._trigger("selecting", event, { 2740 selecting: selectee.element 2741 }); 2742 } else { 2743 self._trigger("unselecting", event, { 2744 unselecting: selectee.element 2745 }); 2746 } 2747 return false; 2748 } 2749 }); 2750 2751 }, 2752 2753 _mouseDrag: function(event) { 2754 var self = this; 2755 this.dragged = true; 2756 2757 if (this.options.disabled) 2758 return; 2759 2760 var options = this.options; 2761 2762 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; 2763 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } 2764 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } 2765 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); 2766 2767 this.selectees.each(function() { 2768 var selectee = $.data(this, "selectable-item"); 2769 //prevent helper from being selected if appendTo: selectable 2770 if (!selectee || selectee.element == self.element[0]) 2771 return; 2772 var hit = false; 2773 if (options.tolerance == 'touch') { 2774 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 2775 } else if (options.tolerance == 'fit') { 2776 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 2777 } 2778 2779 if (hit) { 2780 // SELECT 2781 if (selectee.selected) { 2782 selectee.$element.removeClass('ui-selected'); 2783 selectee.selected = false; 2784 } 2785 if (selectee.unselecting) { 2786 selectee.$element.removeClass('ui-unselecting'); 2787 selectee.unselecting = false; 2788 } 2789 if (!selectee.selecting) { 2790 selectee.$element.addClass('ui-selecting'); 2791 selectee.selecting = true; 2792 // selectable SELECTING callback 2793 self._trigger("selecting", event, { 2794 selecting: selectee.element 2795 });
2796 } 2797 } else { 2798 // UNSELECT 2799 if (selectee.selecting) { 2800 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 2801 selectee.$element.removeClass('ui-selecting'); 2802 selectee.selecting = false; 2803 selectee.$element.addClass('ui-selected'); 2804 selectee.selected = true; 2805 } else { 2806 selectee.$element.removeClass('ui-selecting'); 2807 selectee.selecting = false; 2808 if (selectee.startselected) { 2809 selectee.$element.addClass('ui-unselecting'); 2810 selectee.unselecting = true; 2811 } 2812 // selectable UNSELECTING callback 2813 self._trigger("unselecting", event, { 2814 unselecting: selectee.element 2815 }); 2816 } 2817 } 2818 if (selectee.selected) { 2819 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 2820 selectee.$element.removeClass('ui-selected'); 2821 selectee.selected = false; 2822 2823 selectee.$element.addClass('ui-unselecting'); 2824 selectee.unselecting = true; 2825 // selectable UNSELECTING callback 2826 self._trigger("unselecting", event, { 2827 unselecting: selectee.element 2828 }); 2829 } 2830 } 2831 } 2832 }); 2833 2834 return false; 2835 }, 2836 2837 _mouseStop: function(event) { 2838 var self = this; 2839 2840 this.dragged = false; 2841 2842 var options = this.options; 2843 2844 $('.ui-unselecting', this.element[0]).each(function() { 2845 var selectee = $.data(this, "selectable-item"); 2846 selectee.$element.removeClass('ui-unselecting'); 2847 selectee.unselecting = false; 2848 selectee.startselected = false; 2849 self._trigger("unselected", event, { 2850 unselected: selectee.element 2851 }); 2852 }); 2853 $('.ui-selecting', this.element[0]).each(function() { 2854 var selectee = $.data(this, "selectable-item"); 2855 selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); 2856 selectee.selecting = false; 2857 selectee.selected = true; 2858 selectee.startselected = true; 2859 self._trigger("selected", event, { 2860 selected: selectee.element 2861 }); 2862 }); 2863 this._trigger("stop", event); 2864 2865 this.helper.remove(); 2866 2867 return false; 2868 } 2869 2870}); 2871 2872$.extend($.ui.selectable, { 2873 version: "@VERSION" 2874}); 2875 2876})(jQuery); 2877 2878(function( $, undefined ) { 2879 2880$.widget("ui.sortable", $.ui.mouse, { 2881 widgetEventPrefix: "sort", 2882 ready: false, 2883 options: { 2884 appendTo: "parent", 2885 axis: false, 2886 connectWith: false, 2887 containment: false, 2888 cursor: 'auto', 2889 cursorAt: false, 2890 dropOnEmpty: true, 2891 forcePlaceholderSize: false, 2892 forceHelperSize: false, 2893 grid: false, 2894 handle: false, 2895 helper: "original", 2896 items: '> *', 2897 opacity: false, 2898 placeholder: false, 2899 revert: false, 2900 scroll: true, 2901 scrollSensitivity: 20, 2902 scrollSpeed: 20, 2903 scope: "default", 2904 tolerance: "intersect", 2905 zIndex: 1000 2906 }, 2907 _create: function() { 2908 2909 var o = this.options; 2910 this.containerCache = {}; 2911 this.element.addClass("ui-sortable"); 2912 2913 //Get the items 2914 this.refresh(); 2915 2916 //Let's determine if the items are being displayed horizontally 2917 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; 2918 2919 //Let's determine the parent's offset 2920 this.offset = this.element.offset(); 2921 2922 //Initialize mouse events for interaction 2923 this._mouseInit(); 2924 2925 //We're ready to go 2926 this.ready = true 2927 2928 }, 2929 2930 destroy: function() { 2931 $.Widget.prototype.destroy.call( this ); 2932 this.element 2933 .removeClass("ui-sortable ui-sortable-disabled"); 2934 this._mouseDestroy(); 2935 2936 for ( var i = this.items.length - 1; i >= 0; i-- ) 2937 this.items[i].item.removeData(this.widgetName + "-item"); 2938 2939 return this; 2940 }, 2941 2942 _setOption: function(key, value){ 2943 if ( key === "disabled" ) { 2944 this.options[ key ] = value; 2945 2946 this.widget() 2947 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" ); 2948 } else { 2949 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 2950 $.Widget.prototype._setOption.apply(this, arguments); 2951 } 2952 }, 2953 2954 _mouseCapture: function(event, overrideHandle) { 2955 var that = this; 2956 2957 if (this.reverting) { 2958 return false; 2959 } 2960 2961 if(this.options.disabled || this.options.type == 'static') return false; 2962 2963 //We have to refresh the items data once first 2964 this._refreshItems(event); 2965 2966 //Find out if the clicked node (or one of its parents) is a actual item in this.items 2967 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { 2968 if($.data(this, that.widgetName + '-item') == self) { 2969 currentItem = $(this); 2970 return false; 2971 } 2972 }); 2973 if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target); 2974 2975 if(!currentItem) return false; 2976 if(this.options.handle && !overrideHandle) {
2977 var validHandle = false; 2978 2979 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); 2980 if(!validHandle) return false; 2981 } 2982 2983 this.currentItem = currentItem; 2984 this._removeCurrentsFromItems(); 2985 return true; 2986 2987 }, 2988 2989 _mouseStart: function(event, overrideHandle, noActivation) { 2990 2991 var o = this.options, self = this; 2992 this.currentContainer = this; 2993 2994 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 2995 this.refreshPositions(); 2996 2997 //Create and append the visible helper 2998 this.helper = this._createHelper(event); 2999 3000 //Cache the helper size 3001 this._cacheHelperProportions(); 3002 3003 /* 3004 * - Position generation - 3005 * This block generates everything position related - it's the core of draggables. 3006 */ 3007 3008 //Cache the margins of the original element 3009 this._cacheMargins(); 3010 3011 //Get the next scrolling parent 3012 this.scrollParent = this.helper.scrollParent(); 3013 3014 //The element's absolute position on the page minus margins 3015 this.offset = this.currentItem.offset(); 3016 this.offset = { 3017 top: this.offset.top - this.margins.top, 3018 left: this.offset.left - this.margins.left 3019 }; 3020 3021 // Only after we got the offset, we can change the helper's position to absolute 3022 // TODO: Still need to figure out a way to make relative sorting possible 3023 this.helper.css("position", "absolute"); 3024 this.cssPosition = this.helper.css("position"); 3025 3026 $.extend(this.offset, { 3027 click: { //Where the click happened, relative to the element 3028 left: event.pageX - this.offset.left, 3029 top: event.pageY - this.offset.top 3030 }, 3031 parent: this._getParentOffset(), 3032 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 3033 }); 3034 3035 //Generate the original position 3036 this.originalPosition = this._generatePosition(event); 3037 this.originalPageX = event.pageX; 3038 this.originalPageY = event.pageY; 3039 3040 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied 3041 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 3042 3043 //Cache the former DOM position 3044 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 3045 3046 //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 3047 if(this.helper[0] != this.currentItem[0]) { 3048 this.currentItem.hide(); 3049 } 3050 3051 //Create the placeholder 3052 this._createPlaceholder(); 3053 3054 //Set a containment if given in the options 3055 if(o.containment) 3056 this._setContainment(); 3057 3058 if(o.cursor) { // cursor option 3059 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); 3060 $('body').css("cursor", o.cursor); 3061 } 3062 3063 if(o.opacity) { // opacity option 3064 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); 3065 this.helper.css("opacity", o.opacity); 3066 } 3067 3068 if(o.zIndex) { // zIndex option 3069 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); 3070 this.helper.css("zIndex", o.zIndex); 3071 } 3072 3073 //Prepare scrolling 3074 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') 3075 this.overflowOffset = this.scrollParent.offset(); 3076 3077 //Call callbacks 3078 this._trigger("start", event, this._uiHash()); 3079 3080 //Recache the helper size 3081 if(!this._preserveHelperProportions) 3082 this._cacheHelperProportions(); 3083 3084 3085 //Post 'activate' events to possible containers 3086 if(!noActivation) { 3087 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } 3088 } 3089 3090 //Prepare possible droppables 3091 if($.ui.ddmanager) 3092 $.ui.ddmanager.current = this; 3093 3094 if ($.ui.ddmanager && !o.dropBehaviour) 3095 $.ui.ddmanager.prepareOffsets(this, event); 3096 3097 this.dragging = true; 3098 3099 this.helper.addClass("ui-sortable-helper"); 3100 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 3101 return true; 3102 3103 }, 3104 3105 _mouseDrag: function(event) { 3106 3107 //Compute the helpers position 3108 this.position = this._generatePosition(event); 3109 this.positionAbs = this._convertPositionTo("absolute"); 3110 3111 if (!this.lastPositionAbs) { 3112 this.lastPositionAbs = this.positionAbs; 3113 } 3114 3115 //Do scrolling 3116 if(this.options.scroll) { 3117 var o = this.options, scrolled = false; 3118 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { 3119 3120 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) 3121 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 3122 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) 3123 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 3124 3125 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) 3126 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 3127 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) 3128 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 3129 3130 } else { 3131 3132 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) 3133 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 3134 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) 3135 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 3136 3137 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) 3138 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 3139 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) 3140 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 3141 3142 } 3143 3144 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) 3145 $.ui.ddmanager.prepareOffsets(this, event); 3146 } 3147 3148 //Regenerate the absolute position used for position checks 3149 this.positionAbs = this._convertPositionTo("absolute"); 3150 3151 //Set the helper position 3152 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; 3153 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; 3154 3155 //Rearrange 3156 for (var i = this.items.length - 1; i >= 0; i--) { 3157 3158 //Cache variables and intersection, continue if no intersection 3159 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); 3160 if (!intersection) continue; 3161 3162 if(itemElement != this.currentItem[0] //cannot intersect with itself 3163 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before 3164 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked 3165 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) 3166 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container 3167 ) { 3168 3169 this.direction = intersection == 1 ? "down" : "up"; 3170 3171 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { 3172 this._rearrange(event, item); 3173 } else { 3174 break; 3175 } 3176 3177 this._trigger("change", event, this._uiHash()); 3178 break; 3179 } 3180 } 3181 3182 //Post events to containers 3183 this._contactContainers(event); 3184 3185 //Interconnect with droppables 3186 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); 3187 3188 //Call callbacks 3189 this._trigger('sort', event, this._uiHash()); 3190 3191 this.lastPositionAbs = this.positionAbs; 3192 return false; 3193 3194 }, 3195 3196 _mouseStop: function(event, noPropagation) { 3197 3198 if(!event) return; 3199 3200 //If we are using droppables, inform the manager about the drop 3201 if ($.ui.ddmanager && !this.options.dropBehaviour) 3202 $.ui.ddmanager.drop(this, event); 3203 3204 if(this.options.revert) { 3205 var self = this; 3206 var cur = self.placeholder.offset(); 3207 3208 self.reverting = true; 3209 3210 $(this.helper).animate({ 3211 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), 3212 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) 3213 }, parseInt(this.options.revert, 10) || 500, function() { 3214 self._clear(event); 3215 }); 3216 } else { 3217 this._clear(event, noPropagation); 3218 } 3219 3220 return false; 3221 3222 }, 3223 3224 cancel: function() { 3225 3226 var self = this; 3227 3228 if(this.dragging) { 3229 3230 this._mouseUp({ target: null });
3231 3232 if(this.options.helper == "original") 3233 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 3234 else 3235 this.currentItem.show(); 3236 3237 //Post deactivating events to containers 3238 for (var i = this.containers.length - 1; i >= 0; i--){ 3239 this.containers[i]._trigger("deactivate", null, self._uiHash(this)); 3240 if(this.containers[i].containerCache.over) { 3241 this.containers[i]._trigger("out", null, self._uiHash(this)); 3242 this.containers[i].containerCache.over = 0; 3243 } 3244 } 3245 3246 } 3247 3248 if (this.placeholder) { 3249 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 3250 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 3251 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); 3252 3253 $.extend(this, { 3254 helper: null, 3255 dragging: false, 3256 reverting: false, 3257 _noFinalSort: null 3258 }); 3259 3260 if(this.domPosition.prev) { 3261 $(this.domPosition.prev).after(this.currentItem); 3262 } else { 3263 $(this.domPosition.parent).prepend(this.currentItem); 3264 } 3265 } 3266 3267 return this; 3268 3269 }, 3270 3271 serialize: function(o) { 3272 3273 var items = this._getItemsAsjQuery(o && o.connected); 3274 var str = []; o = o || {}; 3275 3276 $(items).each(function() { 3277 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); 3278 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); 3279 }); 3280 3281 if(!str.length && o.key) { 3282 str.push(o.key + '='); 3283 } 3284 3285 return str.join('&'); 3286 3287 }, 3288 3289 toArray: function(o) { 3290 3291 var items = this._getItemsAsjQuery(o && o.connected); 3292 var ret = []; o = o || {}; 3293 3294 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); 3295 return ret; 3296 3297 }, 3298 3299 /* Be careful with the following core functions */ 3300 _intersectsWith: function(item) { 3301 3302 var x1 = this.positionAbs.left, 3303 x2 = x1 + this.helperProportions.width, 3304 y1 = this.positionAbs.top, 3305 y2 = y1 + this.helperProportions.height; 3306 3307 var l = item.left, 3308 r = l + item.width, 3309 t = item.top, 3310 b = t + item.height; 3311 3312 var dyClick = this.offset.click.top, 3313 dxClick = this.offset.click.left; 3314 3315 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; 3316 3317 if( this.options.tolerance == "pointer" 3318 || this.options.forcePointerForContainers 3319 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) 3320 ) { 3321 return isOverElement; 3322 } else { 3323 3324 return (l < x1 + (this.helperProportions.width / 2) // Right Half 3325 && x2 - (this.helperProportions.width / 2) < r // Left Half 3326 && t < y1 + (this.helperProportions.height / 2) // Bottom Half 3327 && y2 - (this.helperProportions.height / 2) < b ); // Top Half 3328 3329 } 3330 }, 3331 3332 _intersectsWithPointer: function(item) { 3333 3334 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 3335 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 3336 isOverElement = isOverElementHeight && isOverElementWidth, 3337 verticalDirection = this._getDragVerticalDirection(), 3338 horizontalDirection = this._getDragHorizontalDirection(); 3339 3340 if (!isOverElement) 3341 return false; 3342 3343 return this.floating ? 3344 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) 3345 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); 3346 3347 }, 3348 3349 _intersectsWithSides: function(item) { 3350 3351 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 3352 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 3353 verticalDirection = this._getDragVerticalDirection(), 3354 horizontalDirection = this._getDragHorizontalDirection(); 3355 3356 if (this.floating && horizontalDirection) { 3357 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); 3358 } else { 3359 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); 3360 } 3361 3362 }, 3363 3364 _getDragVerticalDirection: function() { 3365 var delta = this.positionAbs.top - this.lastPositionAbs.top; 3366 return delta != 0 && (delta > 0 ? "down" : "up"); 3367 }, 3368 3369 _getDragHorizontalDirection: function() { 3370 var delta = this.positionAbs.left - this.lastPositionAbs.left; 3371 return delta != 0 && (delta > 0 ? "right" : "left"); 3372 }, 3373 3374 refresh: function(event) { 3375 this._refreshItems(event); 3376 this.refreshPositions(); 3377 return this; 3378 }, 3379 3380 _connectWith: function() { 3381 var options = this.options; 3382 return options.connectWith.constructor == String
3383 ? [options.connectWith] 3384 : options.connectWith; 3385 }, 3386 3387 _getItemsAsjQuery: function(connected) { 3388 3389 var self = this; 3390 var items = []; 3391 var queries = []; 3392 var connectWith = this._connectWith(); 3393 3394 if(connectWith && connected) { 3395 for (var i = connectWith.length - 1; i >= 0; i--){ 3396 var cur = $(connectWith[i]); 3397 for (var j = cur.length - 1; j >= 0; j--){ 3398 var inst = $.data(cur[j], this.widgetName); 3399 if(inst && inst != this && !inst.options.disabled) { 3400 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]); 3401 } 3402 }; 3403 }; 3404 } 3405 3406 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]); 3407 3408 for (var i = queries.length - 1; i >= 0; i--){ 3409 queries[i][0].each(function() { 3410 items.push(this); 3411 }); 3412 }; 3413 3414 return $(items); 3415 3416 }, 3417 3418 _removeCurrentsFromItems: function() { 3419 3420 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 3421 3422 for (var i=0; i < this.items.length; i++) { 3423 3424 for (var j=0; j < list.length; j++) { 3425 if(list[j] == this.items[i].item[0]) 3426 this.items.splice(i,1); 3427 }; 3428 3429 }; 3430 3431 }, 3432 3433 _refreshItems: function(event) { 3434 3435 this.items = []; 3436 this.containers = [this]; 3437 var items = this.items; 3438 var self = this; 3439 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; 3440 var connectWith = this._connectWith(); 3441 3442 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 3443 for (var i = connectWith.length - 1; i >= 0; i--){ 3444 var cur = $(connectWith[i]); 3445 for (var j = cur.length - 1; j >= 0; j--){ 3446 var inst = $.data(cur[j], this.widgetName); 3447 if(inst && inst != this && !inst.options.disabled) { 3448 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 3449 this.containers.push(inst); 3450 } 3451 }; 3452 }; 3453 } 3454 3455 for (var i = queries.length - 1; i >= 0; i--) { 3456 var targetData = queries[i][1]; 3457 var _queries = queries[i][0]; 3458 3459 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { 3460 var item = $(_queries[j]); 3461 3462 item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) 3463 3464 items.push({ 3465 item: item, 3466 instance: targetData, 3467 width: 0, height: 0, 3468 left: 0, top: 0 3469 }); 3470 }; 3471 }; 3472 3473 }, 3474 3475 refreshPositions: function(fast) { 3476 3477 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 3478 if(this.offsetParent && this.helper) { 3479 this.offset.parent = this._getParentOffset(); 3480 } 3481 3482 for (var i = this.items.length - 1; i >= 0; i--){ 3483 var item = this.items[i]; 3484 3485 //We ignore calculating positions of all connected containers when we're not over them 3486 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) 3487 continue; 3488 3489 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 3490 3491 if (!fast) { 3492 item.width = t.outerWidth(); 3493 item.height = t.outerHeight(); 3494 } 3495 3496 var p = t.offset(); 3497 item.left = p.left; 3498 item.top = p.top; 3499 }; 3500 3501 if(this.options.custom && this.options.custom.refreshContainers
3501) { 3502 this.options.custom.refreshContainers.call(this); 3503 } else { 3504 for (var i = this.containers.length - 1; i >= 0; i--){ 3505 var p = this.containers[i].element.offset(); 3506 this.containers[i].containerCache.left = p.left; 3507 this.containers[i].containerCache.top = p.top; 3508 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 3509 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 3510 }; 3511 } 3512 3513 return this; 3514 }, 3515 3516 _createPlaceholder: function(that) { 3517 3518 var self = that || this, o = self.options; 3519 3520 if(!o.placeholder || o.placeholder.constructor == String) { 3521 var className = o.placeholder; 3522 o.placeholder = { 3523 element: function() { 3524 3525 var el = $(document.createElement(self.currentItem[0].nodeName)) 3526 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") 3527 .removeClass("ui-sortable-helper").html(" ")[0]; 3528 3529 if(!className) 3530 el.style.visibility = "hidden"; 3531 3532 return el; 3533 }, 3534 update: function(container, p) { 3535 3536 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 3537 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 3538 if(className && !o.forcePlaceholderSize) return; 3539 3540 //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
3541 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; 3542 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; 3543 } 3544 }; 3545 } 3546 3547 //Create the placeholder 3548 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); 3549 3550 //Append it after the actual current item 3551 self.currentItem.after(self.placeholder); 3552 3553 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 3554 o.placeholder.update(self, self.placeholder); 3555 3556 }, 3557 3558 _contactContainers: function(event) { 3559 3560 // get innermost container that intersects with item 3561 var innermostContainer = null, innermostIndex = null; 3562 3563 3564 for (var i = this.containers.length - 1; i >= 0; i--){ 3565 3566 // never consider a container that's located within the item itself 3567 if($.ui.contains(this.currentItem[0], this.containers[i].element[0])) 3568 continue; 3569 3570 if(this._intersectsWith(this.containers[i].containerCache)) { 3571 3572 // if we've already found a container and it's more "inner" than this, then continue 3573 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) 3574 continue; 3575 3576 innermostContainer = this.containers[i]; 3577 innermostIndex = i; 3578 3579 } else { 3580 // container doesn't intersect. trigger "out" event if necessary 3581 if(this.containers[i].containerCache.over) { 3582 this.containers[i]._trigger("out", event, this._uiHash(this)); 3583 this.containers[i].containerCache.over = 0; 3584 } 3585 } 3586 3587 } 3588 3589 // if no intersecting containers found, return 3590 if(!innermostContainer) return; 3591 3592 // move the item into the container if it's not there already 3593 if(this.containers.length === 1) { 3594 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 3595 this.containers[innermostIndex].containerCache.over = 1; 3596 } else if(this.currentContainer != this.containers[innermostIndex]) { 3597 3598 //When entering a new container, we will find the item with the least distance and append our item near it 3599 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 3600 for (var j = this.items.length - 1; j >= 0; j--) { 3601 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 3602 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 3603 if(Math.abs(cur - base) < dist) { 3604 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 3605 } 3606 } 3607 3608 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 3609 return; 3610 3611 this.currentContainer = this.containers[innermostIndex]; 3612 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 3613 this._trigger("change", event, this._uiHash()); 3614 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 3615 3616 //Update the placeholder 3617 this.options.placeholder.update(this.currentContainer, this.placeholder); 3618 3619 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 3620 this.containers[innermostIndex].containerCache.over = 1; 3621 } 3622 3623 3624 }, 3625 3626 _createHelper: function(event) { 3627 3628 var o = this.options; 3629 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); 3630 3631 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already 3632 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 3633 3634 if(helper[0] == this.currentItem[0]) 3635 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
3635: this.currentItem.css("left") }; 3636 3637 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); 3638 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); 3639 3640 return helper; 3641 3642 }, 3643 3644 _adjustOffsetFromHelper: function(obj) { 3645 if (typeof obj == 'string') { 3646 obj = obj.split(' '); 3647 } 3648 if ($.isArray(obj)) { 3649 obj = {left: +obj[0], top: +obj[1] || 0}; 3650 } 3651 if ('left' in obj) { 3652 this.offset.click.left = obj.left + this.margins.left; 3653 } 3654 if ('right' in obj) { 3655 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 3656 } 3657 if ('top' in obj) { 3658 this.offset.click.top = obj.top + this.margins.top; 3659 } 3660 if ('bottom' in obj) { 3661 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 3662 } 3663 }, 3664 3665 _getParentOffset: function() { 3666 3667 3668 //Get the offsetParent and cache its position 3669 this.offsetParent = this.helper.offsetParent(); 3670 var po = this.offsetParent.offset(); 3671 3672 // This is a special case where we need to modify a offset calculated on start, since the following happened: 3673 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 3674 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 3675 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 3676 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { 3677 po.left += this.scrollParent.scrollLeft(); 3678 po.top += this.scrollParent.scrollTop(); 3679 } 3680 3681 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information 3682 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix 3683 po = { top: 0, left: 0 }; 3684 3685 return { 3686 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 3687 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 3688 }; 3689 3690 }, 3691 3692 _getRelativeOffset: function() { 3693 3694 if(this.cssPosition == "relative") { 3695 var p = this.currentItem.position(); 3696 return { 3697 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 3698 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 3699 }; 3700 } else { 3701 return { top: 0, left: 0 }; 3702 } 3703 3704 }, 3705 3706 _cacheMargins: function() { 3707 this.margins = { 3708 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 3709 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 3710 }; 3711 }, 3712 3713 _cacheHelperProportions: function() { 3714 this.helperProportions = { 3715 width: this.helper.outerWidth(), 3716 height: this.helper.outerHeight() 3717 }; 3718 }, 3719 3720 _setContainment: function() { 3721 3722 var o = this.options; 3723 if(o.containment == 'parent') o.containment = this.helper[0].parentNode; 3724 if(o.containment == 'document' || o.containment == 'window') this.containment = [ 3725 0 - this.offset.relative.left - this.offset.parent.left, 3726 0 - this.offset.relative.top - this.offset.parent.top, 3727 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, 3728 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 3729 ]; 3730 3731 if(!(/^(document|window|parent)$/).test(o.containment)) { 3732 var ce = $(o.containment)[0]; 3733 var co = $(o.containment).offset(); 3734 var over = ($(ce).css("overflow") != 'hidden'); 3735 3736 this.containment = [ 3737 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 3738 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 3739 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, 3740 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),
374010) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top 3741 ]; 3742 } 3743 3744 }, 3745 3746 _convertPositionTo: function(d, pos) { 3747 3748 if(!pos) pos = this.position; 3749 var mod = d == "absolute" ? 1 : -1; 3750 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); 3751 3752 return { 3753 top: ( 3754 pos.top // The absolute mouse position 3755 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent 3756 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) 3757 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 3758 ), 3759 left: ( 3760 pos.left // The absolute mouse position 3761 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent 3762 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) 3763 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 3764 ) 3765 }; 3766 3767 }, 3768 3769 _generatePosition: function(event) { 3770 3771 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); 3772 3773 // This is another very weird special case that only happens for relative elements: 3774 // 1. If the css position is relative 3775 // 2. and the scroll parent is the document or similar to the offset parent 3776 // we have to refresh the relative offset during the scroll so there are no jumps 3777 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { 3778 this.offset.relative = this._getRelativeOffset(); 3779 } 3780 3781 var pageX = event.pageX; 3782 var pageY = event.pageY; 3783 3784 /* 3785 * - Position constraining - 3786 * Constrain the position to a mix of grid, containment. 3787 */ 3788 3789 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 3790 3791 if(this.containment) { 3792 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; 3793 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; 3794 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; 3795 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; 3796 } 3797 3798 if(o.grid) { 3799 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 3800 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; 3801 3802 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 3803 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; 3804 } 3805 3806 } 3807 3808 return { 3809 top: ( 3810 pageY // The absolute mouse position 3811 - this.offset.click.top // Click offset (relative to the element) 3812 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent 3813 - this.offset.parent.top // The offsetParent's offset without borders (offset + border) 3814 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 3815 ), 3816 left: ( 3817 pageX // The absolute mouse position 3818 - this.offset.click.left // Click offset (relative to the element) 3819 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent 3820 - this.offset.parent.left // The offsetParent's offset without borders (offset + border) 3821 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 3822 ) 3823 }; 3824 3825 }, 3826 3827 _rearrange: function(event, i, a, hardRefresh) { 3828 3829 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)); 3830 3831 //Various things done here to improve the performance: 3832 // 1. we create a setTimeout, that calls refreshPositions 3833 // 2. on the instance, we have a counter variable, that get's higher after every append 3834 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 3835 // 4. this lets only the last addition to the timeout stack through 3836 this.counter = this.counter ? ++this.counter : 1;
3837 var self = this, counter = this.counter; 3838 3839 window.setTimeout(function() { 3840 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 3841 },0); 3842 3843 }, 3844 3845 _clear: function(event, noPropagation) { 3846 3847 this.reverting = false; 3848 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 3849 // everything else normalized again 3850 var delayedTriggers = [], self = this; 3851 3852 // We first have to update the dom position of the actual currentItem 3853 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 3854 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); 3855 this._noFinalSort = null; 3856 3857 if(this.helper[0] == this.currentItem[0]) { 3858 for(var i in this._storedCSS) { 3859 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; 3860 } 3861 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 3862 } else { 3863 this.currentItem.show(); 3864 } 3865 3866 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 3867 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 3868 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element 3869 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 3870 for (var i = this.containers.length - 1; i >= 0; i--){ 3871 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { 3872 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 3873 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 3874 } 3875 }; 3876 }; 3877 3878 //Post events to containers 3879 for (var i = this.containers.length - 1; i >= 0; i--){ 3880 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 3881 if(this.containers[i].containerCache.over) { 3882 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 3883 this.containers[i].containerCache.over = 0; 3884 } 3885 } 3886 3887 //Do what was originally in plugins 3888 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor 3889 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity 3890 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index 3891 3892 this.dragging = false; 3893 if(this.cancelHelperRemoval) { 3894 if(!noPropagation) { 3895 this._trigger("beforeStop", event, this._uiHash()); 3896 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events 3897 this._trigger("stop", event, this._uiHash()); 3898 } 3899 return false; 3900 } 3901 3902 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); 3903 3904 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 3905 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 3906 3907 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; 3908 3909 if(!noPropagation) { 3910 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events 3911 this._trigger("stop", event, this._uiHash()); 3912 } 3913 3914 this.fromOutside = false; 3915 return true; 3916 3917 }, 3918 3919 _trigger: function() { 3920 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 3921 this.cancel(); 3922 } 3923 }, 3924 3925 _uiHash: function(inst) { 3926 var self = inst || this; 3927 return { 3928 helper: self.helper, 3929 placeholder: self.placeholder || $([]), 3930 position: self.position, 3931 originalPosition: self.originalPosition, 3932 offset: self.positionAbs, 3933 item: self.currentItem, 3934 sender: inst ? inst.element : null 3935 }; 3936 } 3937 3938}); 3939 3940$.extend($.ui.sortable, { 3941 version: "@VERSION" 3942}); 3943 3944})(jQuery); 3945 3946;jQuery.effects || (function($, undefined) { 3947 3948$.effects = {}; 3949 3950 3951 3952/******************************************************************************/ 3953/****************************** COLOR ANIMATIONS ******************************/ 3954/******************************************************************************/ 3955 3956// override the animation for color styles 3957$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 3958 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'], 3959function(i, attr) { 3960 $.fx.step[attr] = function(fx) { 3961 if (!fx.colorInit) { 3962 fx.start = getColor(fx.elem, attr); 3963 fx.end = getRGB(fx.end); 3964 fx.colorInit = true; 3965 } 3966 3967 fx.elem.style[attr] = 'rgb(' + 3968 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0
3968) + ',' + 3969 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' + 3970 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')'; 3971 }; 3972}); 3973 3974// Color Conversion functions from highlightFade 3975// By Blair Mitchelmore 3976// http://jquery.offput.ca/highlightFade/ 3977 3978// Parse strings looking for color tuples [255,255,255] 3979function getRGB(color) { 3980 var result; 3981 3982 // Check if we're already dealing with an array of colors 3983 if ( color && color.constructor == Array && color.length == 3 ) 3984 return color; 3985 3986 // Look for rgb(num,num,num) 3987 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) 3988 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; 3989 3990 // Look for rgb(num%,num%,num%) 3991 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) 3992 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; 3993 3994 // Look for #a0b1c2 3995 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) 3996 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; 3997 3998 // Look for #fff 3999 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) 4000 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; 4001 4002 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 4003 if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) 4004 return colors['transparent']; 4005 4006 // Otherwise, we're most likely dealing with a named color 4007 return colors[$.trim(color).toLowerCase()]; 4008} 4009 4010function getColor(elem, attr) { 4011 var color; 4012 4013 do { 4014 color = $.curCSS(elem, attr); 4015 4016 // Keep going until we find an element that has color, or we hit the body 4017 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) 4018 break; 4019 4020 attr = "backgroundColor"; 4021 } while ( elem = elem.parentNode ); 4022 4023 return getRGB(color); 4024}; 4025 4026// Some named colors to work with 4027// From Interface by Stefan Petre 4028// http://interface.eyecon.ro/ 4029 4030var colors = { 4031 aqua:[0,255,255], 4032 azure:[240,255,255], 4033 beige:[245,245,220], 4034 black:[0,0,0], 4035 blue:[0,0,255], 4036 brown:[165,42,42], 4037 cyan:[0,255,255], 4038 darkblue:[0,0,139], 4039 darkcyan:[0,139,139], 4040 darkgrey:[169,169,169], 4041 darkgreen:[0,100,0], 4042 darkkhaki:[189,183,107], 4043 darkmagenta:[139,0,139], 4044 darkolivegreen:[85,107,47], 4045 darkorange:[255,140,0], 4046 darkorchid:[153,50,204], 4047 darkred:[139,0,0], 4048 darksalmon:[233,150,122], 4049 darkviolet:[148,0,211], 4050 fuchsia:[255,0,255], 4051 gold:[255,215,0], 4052 green:[0,128,0], 4053 indigo:[75,0,130], 4054 khaki:[240,230,140], 4055 lightblue:[173,216,230], 4056 lightcyan:[224,255,255], 4057 lightgreen:[144,238,144], 4058 lightgrey:[211,211,211], 4059 lightpink:[255,182,193], 4060 lightyellow:[255,255,224], 4061 lime:[0,255,0], 4062 magenta:[255,0,255], 4063 maroon:[128,0,0], 4064 navy:[0,0,128], 4065 olive:[128,128,0], 4066 orange:[255,165,0], 4067 pink:[255,192,203], 4068 purple:[128,0,128], 4069 violet:[128,0,128], 4070 red:[255,0,0], 4071 silver:[192,192,192], 4072 white:[255,255,255], 4073 yellow:[255,255,0], 4074 transparent: [255,255,255] 4075}; 4076 4077 4078 4079/******************************************************************************/ 4080/****************************** CLASS ANIMATIONS ******************************/ 4081/******************************************************************************/ 4082 4083var classAnimationActions = ['add', 'remove', 'toggle'], 4084 shorthandStyles = { 4085 border: 1, 4086 borderBottom: 1, 4087 borderColor: 1, 4088 borderLeft: 1, 4089 borderRight: 1, 4090 borderTop: 1, 4091 borderWidth: 1, 4092 margin: 1, 4093 padding: 1 4094 }; 4095 4096function getElementStyles() { 4097 var style = document.defaultView 4098 ? document.defaultView.getComputedStyle(this, null) 4099 : this.currentStyle, 4100 newStyle = {}, 4101 key, 4102 camelCase; 4103 4104 // webkit enumerates style porperties 4105 if (style && style.length && style[0] && style[style[0]]) { 4106 var len = style.length; 4107 while (len--) { 4108 key = style[len]; 4109 if (typeof style[key] == 'string') { 4110 camelCase = key.replace(/\-(\w)/g, function(all, letter){ 4111 return letter.toUpperCase(); 4112 }); 4113 newStyle[camelCase] = style[key]; 4114 } 4115 } 4116 } else { 4117 for (key in style) { 4118 if (typeof style[key] === 'string') { 4119 newStyle[key] = style[key]; 4120 } 4121 } 4122 } 4123 4124 return newStyle; 4125} 4126 4127function filterStyles(styles) { 4128 var name, value; 4129 for (name in styles) { 4130 value = styles[name]; 4131 if ( 4132 // ignore null and undefined values 4133 value == null || 4134 // ignore functions (when does this occur?) 4135 $.isFunction(value) || 4136 // shorthand styles that need to be expanded 4137 name in shorthandStyles || 4138 // ignore scrollbars (break in IE) 4139 (/scrollbar/).test(name) || 4140 4141 // only colors or values that can be converted to numbers 4142 (!(/color/i).test(name) && isNaN(parseFloat(value))) 4143 ) { 4144 delete styles[name]; 4145 } 4146 } 4147 4148 return styles; 4149} 4150 4151function styleDifference(oldStyle, newStyle) { 4152 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459 4153 name; 4154 4155 for (name in newStyle) { 4156 if (oldStyle[name] != newStyle[name]) { 4157 diff[name] = newStyle[name]; 4158 } 4159 } 4160 4161 return diff; 4162} 4163 4164$.effects.animateClass = function(value, duration, easing, callback) { 4165 if ($.isFunction(easing)) { 4166 callback = easing; 4167 easing = null; 4168 } 4169 4170 return this.queue(function() { 4171 var that = $(this), 4172 originalStyleAttr = that.attr('style') || ' ', 4173 originalStyle = filterStyles(getElementStyles.call(this)), 4174 newStyle, 4175 className = that.attr('class') || ""; 4176 4177 $.each(classAnimationActions, function(i, action) { 4178 if (value[action]) { 4179 that[action + 'Class'](value[action]); 4180 } 4181 }); 4182 newStyle = filterStyles(getElementStyles.call(this)); 4183 that.attr('class', className); 4184 4185 that.animate(styleDifference(originalStyle, newStyle), { 4186 queue: false, 4187 duration: duration, 4188 easing: easing,
4189 complete: function() { 4190 $.each(classAnimationActions, function(i, action) { 4191 if (value[action]) { that[action + 'Class'](value[action]); } 4192 }); 4193 // work around bug in IE by clearing the cssText before setting it 4194 if (typeof that.attr('style') == 'object') { 4195 that.attr('style').cssText = ''; 4196 that.attr('style').cssText = originalStyleAttr; 4197 } else { 4198 that.attr('style', originalStyleAttr); 4199 } 4200 if (callback) { callback.apply(this, arguments); } 4201 $.dequeue( this ); 4202 } 4203 }); 4204 }); 4205}; 4206 4207$.fn.extend({ 4208 _addClass: $.fn.addClass, 4209 addClass: function(classNames, speed, easing, callback) { 4210 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); 4211 }, 4212 4213 _removeClass: $.fn.removeClass, 4214 removeClass: function(classNames,speed,easing,callback) { 4215 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); 4216 }, 4217 4218 _toggleClass: $.fn.toggleClass, 4219 toggleClass: function(classNames, force, speed, easing, callback) { 4220 if ( typeof force == "boolean" || force === undefined ) { 4221 if ( !speed ) { 4222 // without speed parameter; 4223 return this._toggleClass(classNames, force); 4224 } else { 4225 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]); 4226 } 4227 } else { 4228 // without switch parameter; 4229 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]); 4230 } 4231 }, 4232 4233 switchClass: function(remove,add,speed,easing,callback) { 4234 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); 4235 } 4236}); 4237 4238 4239 4240/******************************************************************************/ 4241/*********************************** EFFECTS **********************************/ 4242/******************************************************************************/ 4243 4244$.extend($.effects, { 4245 version: "@VERSION", 4246 4247 // Saves a set of properties in a data storage 4248 save: function(element, set) { 4249 for(var i=0; i < set.length; i++) { 4250 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]); 4251 } 4252 }, 4253 4254 // Restores a set of previously saved properties from a data storage 4255 restore: function(element, set) { 4256 for(var i=0; i < set.length; i++) { 4257 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i])); 4258 } 4259 }, 4260 4261 setMode: function(el, mode) { 4262 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle 4263 return mode; 4264 }, 4265 4266 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value 4267 // this should be a little more flexible in the future to handle a string & hash 4268 var y, x; 4269 switch (origin[0]) { 4270 case 'top': y = 0; break; 4271 case 'middle': y = 0.5; break; 4272 case 'bottom': y = 1; break; 4273 default: y = origin[0] / original.height; 4274 }; 4275 switch (origin[1]) { 4276 case 'left': x = 0; break; 4277 case 'center': x = 0.5; break; 4278 case 'right': x = 1; break; 4279 default: x = origin[1] / original.width; 4280 }; 4281 return {x: x, y: y}; 4282 }, 4283 4284 // Wraps the element around a wrapper that copies position properties 4285 createWrapper: function(element) { 4286 4287 // if the element is already wrapped, return it 4288 if (element.parent().is('.ui-effects-wrapper')) { 4289 return element.parent(); 4290 } 4291 4292 // wrap the element 4293 var props = { 4294 width: element.outerWidth(true), 4295 height: element.outerHeight(true), 4296 'float': element.css('float') 4297 }, 4298 wrapper = $('<div></div>') 4299 .addClass('ui-effects-wrapper') 4300 .css({ 4301 fontSize: '100%', 4302 background: 'transparent', 4303 border: 'none', 4304 margin: 0, 4305 padding: 0 4306 }), 4307 active = document.activeElement; 4308 4309 element.wrap(wrapper); 4310 4311 // Fixes #7595 - Elements lose focus when wrapped. 4312 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 4313 $( active ).focus(); 4314 } 4315 4316 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element 4317 4318 // transfer positioning properties to the wrapper 4319 if (element.css('position') == 'static') { 4320 wrapper.css({ position: 'relative' }); 4321 element.css({ position: 'relative' }); 4322 } else { 4323 $.extend(props, { 4324 position: element.css('position'), 4325 zIndex: element.css('z-index') 4326 }); 4327 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) { 4328 props[pos] = element.css(pos); 4329 if (isNaN(parseInt(props[pos], 10))) { 4330 props[pos] = 'auto'; 4331 } 4332 }); 4333 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
4334 } 4335 4336 return wrapper.css(props).show(); 4337 }, 4338 4339 removeWrapper: function(element) { 4340 var parent, 4341 active = document.activeElement; 4342 4343 if (element.parent().is('.ui-effects-wrapper')) { 4344 parent = element.parent().replaceWith(element); 4345 // Fixes #7595 - Elements lose focus when wrapped. 4346 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 4347 $( active ).focus(); 4348 } 4349 return parent; 4350 } 4351 4352 return element; 4353 }, 4354 4355 setTransition: function(element, list, factor, value) { 4356 value = value || {}; 4357 $.each(list, function(i, x){ 4358 var unit = element.cssUnit(x); 4359 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1]; 4360 }); 4361 return value; 4362 } 4363}); 4364 4365 4366function _normalizeArguments(effect, options, speed, callback) { 4367 // shift params for method overloading 4368 if (typeof effect == 'object') { 4369 callback = options; 4370 speed = null; 4371 options = effect; 4372 effect = options.effect; 4373 } 4374 if ($.isFunction(options)) { 4375 callback = options; 4376 speed = null; 4377 options = {}; 4378 } 4379 if (typeof options == 'number' || $.fx.speeds[options]) { 4380 callback = speed; 4381 speed = options; 4382 options = {}; 4383 } 4384 if ($.isFunction(speed)) { 4385 callback = speed; 4386 speed = null; 4387 } 4388 4389 options = options || {}; 4390 4391 speed = speed || options.duration; 4392 speed = $.fx.off ? 0 : typeof speed == 'number' 4393 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default; 4394 4395 callback = callback || options.complete; 4396 4397 return [effect, options, speed, callback]; 4398} 4399 4400function standardSpeed( speed ) { 4401 // valid standard speeds 4402 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { 4403 return true; 4404 } 4405 4406 // invalid strings - treat as "normal" speed 4407 if ( typeof speed === "string" && !$.effects[ speed ] ) { 4408 return true; 4409 } 4410 4411 return false; 4412} 4413 4414$.fn.extend({ 4415 effect: function(effect, options, speed, callback) { 4416 var args = _normalizeArguments.apply(this, arguments), 4417 // TODO: make effects take actual parameters instead of a hash 4418 args2 = { 4419 options: args[1], 4420 duration: args[2], 4421 callback: args[3] 4422 }, 4423 mode = args2.options.mode, 4424 effectMethod = $.effects[effect]; 4425 4426 if ( $.fx.off || !effectMethod ) { 4427 // delegate to the original method (e.g., .show()) if possible 4428 if ( mode ) { 4429 return this[ mode ]( args2.duration, args2.callback ); 4430 } else { 4431 return this.each(function() { 4432 if ( args2.callback ) { 4433 args2.callback.call( this ); 4434 } 4435 }); 4436 } 4437 } 4438 4439 return effectMethod.call(this, args2); 4440 }, 4441 4442 _show: $.fn.show, 4443 show: function(speed) { 4444 if ( standardSpeed( speed ) ) { 4445 return this._show.apply(this, arguments); 4446 } else { 4447 var args = _normalizeArguments.apply(this, arguments); 4448 args[1].mode = 'show'; 4449 return this.effect.apply(this, args); 4450 } 4451 }, 4452 4453 _hide: $.fn.hide, 4454 hide: function(speed) { 4455 if ( standardSpeed( speed ) ) { 4456 return this._hide.apply(this, arguments); 4457 } else { 4458 var args = _normalizeArguments.apply(this, arguments); 4459 args[1].mode = 'hide'; 4460 return this.effect.apply(this, args); 4461 } 4462 }, 4463 4464 // jQuery core overloads toggle and creates _toggle 4465 __toggle: $.fn.toggle, 4466 toggle: function(speed) { 4467 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { 4468 return this.__toggle.apply(this, arguments); 4469 } else { 4470 var args = _normalizeArguments.apply(this, arguments); 4471 args[1].mode = 'toggle'; 4472 return this.effect.apply(this, args); 4473 } 4474 }, 4475 4476 // helper functions 4477 cssUnit: function(key) { 4478 var style = this.css(key), val = []; 4479 $.each( ['em','px','%','pt'], function(i, unit){ 4480 if(style.indexOf(unit) > 0) 4481 val = [parseFloat(style), unit]; 4482 }); 4483 return val; 4484 } 4485}); 4486 4487 4488 4489/******************************************************************************/ 4490/*********************************** EASING ***********************************/ 4491/******************************************************************************/ 4492 4493/* 4494 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 4495 * 4496 * Uses the built in easing capabilities added In jQuery 1.1 4497 * to offer multiple easing options 4498 * 4499 * TERMS OF USE - jQuery Easing 4500 * 4501 * Open source under the BSD License. 4502 * 4503 * Copyright 2008 George McGinley Smith 4504 * All rights reserved. 4505 * 4506 * Redistribution and use in source and binary forms, with or without modification, 4507 * are permitted provided that the following conditions are met: 4508 * 4509 * Redistributions of source code must retain the above copyright notice, this list of 4510 * conditions and the following disclaimer. 4511 * Redistributions in binary form must reproduce the above copyright notice, this list 4512 * of conditions and the following disclaimer in the documentation and/or other materials 4513 * provided with the distribution. 4514 * 4515 * Neither the name of the author nor the names of contributors may be used to endorse
vendor: 5,639 bytes, lines 4516-4667
4516 * or promote products derived from this software without specific prior written permission. 4517 * 4518 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 4519 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 4520 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 4521 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 4522 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 4523 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 4524 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 4525 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4526 * OF THE POSSIBILITY OF SUCH DAMAGE. 4527 * 4528*/ 4529 4530// t: current time, b: begInnIng value, c: change In value, d: duration 4531$.easing.jswing = $.easing.swing; 4532 4533$.extend($.easing, 4534{ 4535 def: 'easeOutQuad', 4536 swing: function (x, t, b, c, d) { 4537 //alert($.easing.default); 4538 return $.easing[$.easing.def](x, t, b, c, d); 4539 }, 4540 easeInQuad: function (x, t, b, c, d) { 4541 return c*(t/=d)*t + b; 4542 }, 4543 easeOutQuad: function (x, t, b, c, d) { 4544 return -c *(t/=d)*(t-2) + b; 4545 }, 4546 easeInOutQuad: function (x, t, b, c, d) { 4547 if ((t/=d/2) < 1) return c/2*t*t + b; 4548 return -c/2 * ((--t)*(t-2) - 1) + b; 4549 }, 4550 easeInCubic: function (x, t, b, c, d) { 4551 return c*(t/=d)*t*t + b; 4552 }, 4553 easeOutCubic: function (x, t, b, c, d) { 4554 return c*((t=t/d-1)*t*t + 1) + b; 4555 }, 4556 easeInOutCubic: function (x, t, b, c, d) { 4557 if ((t/=d/2) < 1) return c/2*t*t*t + b; 4558 return c/2*((t-=2)*t*t + 2) + b; 4559 }, 4560 easeInQuart: function (x, t, b, c, d) { 4561 return c*(t/=d)*t*t*t + b; 4562 }, 4563 easeOutQuart: function (x, t, b, c, d) { 4564 return -c * ((t=t/d-1)*t*t*t - 1) + b; 4565 }, 4566 easeInOutQuart: function (x, t, b, c, d) { 4567 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 4568 return -c/2 * ((t-=2)*t*t*t - 2) + b; 4569 }, 4570 easeInQuint: function (x, t, b, c, d) { 4571 return c*(t/=d)*t*t*t*t + b; 4572 }, 4573 easeOutQuint: function (x, t, b, c, d) { 4574 return c*((t=t/d-1)*t*t*t*t + 1) + b; 4575 }, 4576 easeInOutQuint: function (x, t, b, c, d) { 4577 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 4578 return c/2*((t-=2)*t*t*t*t + 2) + b; 4579 }, 4580 easeInSine: function (x, t, b, c, d) { 4581 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 4582 }, 4583 easeOutSine: function (x, t, b, c, d) { 4584 return c * Math.sin(t/d * (Math.PI/2)) + b; 4585 }, 4586 easeInOutSine: function (x, t, b, c, d) { 4587 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 4588 }, 4589 easeInExpo: function (x, t, b, c, d) { 4590 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 4591 }, 4592 easeOutExpo: function (x, t, b, c, d) { 4593 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 4594 }, 4595 easeInOutExpo: function (x, t, b, c, d) { 4596 if (t==0) return b; 4597 if (t==d) return b+c; 4598 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 4599 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 4600 }, 4601 easeInCirc: function (x, t, b, c, d) { 4602 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 4603 }, 4604 easeOutCirc: function (x, t, b, c, d) { 4605 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 4606 }, 4607 easeInOutCirc: function (x, t, b, c, d) { 4608 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 4609 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 4610 }, 4611 easeInElastic: function (x, t, b, c, d) { 4612 var s=1.70158;var p=0;var a=c; 4613 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 4614 if (a < Math.abs(c)) { a=c; var s=p/4; } 4615 else var s = p/(2*Math.PI) * Math.asin (c/a); 4616 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 4617 }, 4618 easeOutElastic: function (x, t, b, c, d) { 4619 var s=1.70158;var p=0;var a=c; 4620 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 4621 if (a < Math.abs(c)) { a=c; var s=p/4; } 4622 else var s = p/(2*Math.PI) * Math.asin (c/a); 4623 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 4624 }, 4625 easeInOutElastic: function (x, t, b, c, d) { 4626 var s=1.70158;var p=0;var a=c; 4627 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 4628 if (a < Math.abs(c)) { a=c; var s=p/4; } 4629 else var s = p/(2*Math.PI) * Math.asin (c/a); 4630 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 4631 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 4632 }, 4633 easeInBack: function (x, t, b, c, d, s) { 4634 if (s == undefined) s = 1.70158; 4635 return c*(t/=d)*t*((s+1)*t - s) + b; 4636 }, 4637 easeOutBack: function (x, t, b, c, d, s) { 4638 if (s == undefined) s = 1.70158; 4639 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 4640 }, 4641 easeInOutBack: function (x, t, b, c, d, s) { 4642 if (s == undefined) s = 1.70158; 4643 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 4644 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 4645 }, 4646 easeInBounce: function (x, t, b, c, d) { 4647 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b; 4648 }, 4649 easeOutBounce: function (x, t, b, c, d) { 4650 if ((t/=d) < (1/2.75)) { 4651 return c*(7.5625*t*t) + b; 4652 } else if (t < (2/2.75)) { 4653 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 4654 } else if (t < (2.5/2.75)) { 4655 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 4656 } else { 4657 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 4658 } 4659 }, 4660 easeInOutBounce: function (x, t, b, c, d) { 4661 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 4662 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 4663 } 4664}); 4665 4666/* 4667 *
4668 * TERMS OF USE - EASING EQUATIONS 4669 * 4670 * Open source under the BSD License. 4671 * 4672 * Copyright 2001 Robert Penner 4673 * All rights reserved. 4674 * 4675 * Redistribution and use in source and binary forms, with or without modification, 4676 * are permitted provided that the following conditions are met: 4677 * 4678 * Redistributions of source code must retain the above copyright notice, this list of 4679 * conditions and the following disclaimer. 4680 * Redistributions in binary form must reproduce the above copyright notice, this list 4681 * of conditions and the following disclaimer in the documentation and/or other materials 4682 * provided with the distribution. 4683 * 4684 * Neither the name of the author nor the names of contributors may be used to endorse 4685 * or promote products derived from this software without specific prior written permission. 4686 * 4687 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 4688 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 4689 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 4690 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 4691 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 4692 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 4693 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 4694 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4695 * OF THE POSSIBILITY OF SUCH DAMAGE. 4696 * 4697 */ 4698 4699})(jQuery); 4700 4701(function( $, undefined ) { 4702 4703$.effects.blind = function(o) { 4704 4705 return this.queue(function() { 4706 4707 // Create element 4708 var el = $(this), props = ['position','top','bottom','left','right']; 4709 4710 // Set options 4711 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4712 var direction = o.options.direction || 'vertical'; // Default direction 4713 4714 // Adjust 4715 $.effects.save(el, props); el.show(); // Save & Show 4716 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 4717 var ref = (direction == 'vertical') ? 'height' : 'width'; 4718 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width(); 4719 if(mode == 'show') wrapper.css(ref, 0); // Shift 4720 4721 // Animation 4722 var animation = {}; 4723 animation[ref] = mode == 'show' ? distance : 0; 4724 4725 // Animate 4726 wrapper.animate(animation, o.duration, o.options.easing, 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.bounce = function(o) { 4742 4743 return this.queue(function() { 4744 4745 // Create element 4746 var el = $(this), props = ['position','top','bottom','left','right']; 4747 4748 // Set options 4749 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 4750 var direction = o.options.direction || 'up'; // Default direction 4751 var distance = o.options.distance || 20; // Default distance 4752 var times = o.options.times || 5; // Default # of times 4753 var speed = o.duration || 250; // Default speed per bounce 4754 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE 4755 4756 // Adjust 4757 $.effects.save(el, props); el.show(); // Save & Show 4758 $.effects.createWrapper(el); // Create Wrapper 4759 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 4760 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 4761 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3); 4762 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift 4763 if (mode == 'hide') distance = distance / (times * 2); 4764 if (mode != 'hide') times--; 4765 4766 // Animate 4767 if (mode == 'show') { // Show Bounce 4768 var animation = {opacity: 1}; 4769 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance; 4770 el.animate(animation, speed / 2, o.options.easing); 4771 distance = distance / 2; 4772 times--; 4773 }; 4774 for (var i = 0; i < times; i++) { // Bounces 4775 var animation1 = {}, animation2 = {}; 4776 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 4777 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; 4778 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing); 4779 distance = (mode == 'hide') ? distance * 2 : distance / 2; 4780 }; 4781 if (mode == 'hide') { // Last Bounce 4782 var animation = {opacity: 0}; 4783 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 4784 el.animate(animation, speed / 2, o.options.easing, function(){ 4785 el.hide(); // Hide 4786 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4787 if(o.callback) o.callback.apply(this, arguments); // Callback 4788 }); 4789 } else { 4790 var animation1 = {}, animation2 = {}; 4791 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 4792 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; 4793 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){ 4794 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4795 if(o.callback) o.callback.apply(this, arguments); // Callback 4796 }); 4797 }; 4798 el.queue('fx', function() { el.dequeue(); }); 4799 el.dequeue(); 4800 }); 4801 4802}; 4803 4804})(jQuery); 4805 4806(function( $, undefined ) { 4807 4808$.effects.clip = function(o) { 4809 4810 return this.queue(function() { 4811 4812 // Create element 4813 var el = $(this), props = ['position','top','bottom','left','right','height','width']; 4814 4815 // Set options 4816 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4817 var direction = o.options.direction || 'vertical'; // Default direction 4818 4819 // Adjust 4820 $.effects.save(el, props); el.show(); // Save & Show 4821 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 4822 var animate = el[0].tagName == 'IMG' ? wrapper : el; 4823 var ref = { 4824 size: (direction == 'vertical') ? 'height' : 'width', 4825 position: (direction == 'vertical') ? 'top' : 'left' 4826 }; 4827 var distance = (direction == 'vertical') ? animate.height() : animate.width(); 4828 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift 4829 4830 // Animation 4831 var animation = {};
4832 animation[ref.size] = mode == 'show' ? distance : 0; 4833 animation[ref.position] = mode == 'show' ? 0 : distance / 2; 4834 4835 // Animate 4836 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 4837 if(mode == 'hide') el.hide(); // Hide 4838 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4839 if(o.callback) o.callback.apply(el[0], arguments); // Callback 4840 el.dequeue(); 4841 }}); 4842 4843 }); 4844 4845}; 4846 4847})(jQuery); 4848 4849(function( $, undefined ) { 4850 4851$.effects.drop = function(o) { 4852 4853 return this.queue(function() { 4854 4855 // Create element 4856 var el = $(this), props = ['position','top','bottom','left','right','opacity']; 4857 4858 // Set options 4859 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4860 var direction = o.options.direction || 'left'; // Default Direction 4861 4862 // Adjust 4863 $.effects.save(el, props); el.show(); // Save & Show 4864 $.effects.createWrapper(el); // Create Wrapper 4865 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 4866 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 4867 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2); 4868 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift 4869 4870 // Animation 4871 var animation = {opacity: mode == 'show' ? 1 : 0}; 4872 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; 4873 4874 // Animate 4875 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 4876 if(mode == 'hide') el.hide(); // Hide 4877 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4878 if(o.callback) o.callback.apply(this, arguments); // Callback 4879 el.dequeue(); 4880 }}); 4881 4882 }); 4883 4884}; 4885 4886})(jQuery); 4887 4888(function( $, undefined ) { 4889 4890$.effects.explode = function(o) { 4891 4892 return this.queue(function() { 4893 4894 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; 4895 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; 4896 4897 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode; 4898 var el = $(this).show().css('visibility', 'hidden'); 4899 var offset = el.offset(); 4900 4901 //Substract the margins - not fixing the problem yet. 4902 offset.top -= parseInt(el.css("marginTop"),10) || 0; 4903 offset.left -= parseInt(el.css("marginLeft"),10) || 0; 4904 4905 var width = el.outerWidth(true); 4906 var height = el.outerHeight(true); 4907 4908 for(var i=0;i<rows;i++) { // = 4909 for(var j=0;j<cells;j++) { // || 4910 el 4911 .clone() 4912 .appendTo('body') 4913 .wrap('<div></div>') 4914 .css({ 4915 position: 'absolute', 4916 visibility: 'visible', 4917 left: -j*(width/cells), 4918 top: -i*(height/rows) 4919 }) 4920 .parent() 4921 .addClass('ui-effects-explode') 4922 .css({ 4923 position: 'absolute', 4924 overflow: 'hidden', 4925 width: width/cells, 4926 height: height/rows, 4927 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0), 4928 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0), 4929 opacity: o.options.mode == 'show' ? 0 : 1 4930 }).animate({ 4931 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)), 4932 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)), 4933 opacity: o.options.mode == 'show' ? 1 : 0 4934 }, o.duration || 500); 4935 } 4936 } 4937 4938 // Set a timeout, to call the callback approx. when the other animations have finished 4939 setTimeout(function() { 4940 4941 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide(); 4942 if(o.callback) o.callback.apply(el[0]); // Callback 4943 el.dequeue(); 4944 4945 $('div.ui-effects-explode').remove(); 4946 4947 }, o.duration || 500); 4948 4949 4950 }); 4951 4952}; 4953 4954})(jQuery); 4955 4956(function( $, undefined ) { 4957 4958$.effects.fade = function(o) { 4959 return this.queue(function() { 4960 var elem = $(this), 4961 mode = $.effects.setMode(elem, o.options.mode || 'hide'); 4962 4963 elem.animate({ opacity: mode }, { 4964 queue: false, 4965 duration: o.duration, 4966 easing: o.options.easing,
4967 complete: function() { 4968 (o.callback && o.callback.apply(this, arguments)); 4969 elem.dequeue(); 4970 } 4971 }); 4972 }); 4973}; 4974 4975})(jQuery); 4976 4977(function( $, undefined ) { 4978 4979$.effects.fold = function(o) { 4980 4981 return this.queue(function() { 4982 4983 // Create element 4984 var el = $(this), props = ['position','top','bottom','left','right']; 4985 4986 // Set options 4987 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4988 var size = o.options.size || 15; // Default fold size 4989 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value 4990 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; 4991 4992 // Adjust 4993 $.effects.save(el, props); el.show(); // Save & Show 4994 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 4995 var widthFirst = ((mode == 'show') != horizFirst); 4996 var ref = widthFirst ? ['width', 'height'] : ['height', 'width']; 4997 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()]; 4998 var percent = /([0-9]+)%/.exec(size); 4999 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1]; 5000 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift 5001 5002 // Animation 5003 var animation1 = {}, animation2 = {}; 5004 animation1[ref[0]] = mode == 'show' ? distance[0] : size; 5005 animation2[ref[1]] = mode == 'show' ? distance[1] : 0; 5006 5007 // Animate 5008 wrapper.animate(animation1, duration, o.options.easing) 5009 .animate(animation2, duration, o.options.easing, function() { 5010 if(mode == 'hide') el.hide(); // Hide 5011 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 5012 if(o.callback) o.callback.apply(el[0], arguments); // Callback 5013 el.dequeue(); 5014 }); 5015 5016 }); 5017 5018}; 5019 5020})(jQuery); 5021 5022(function( $, undefined ) { 5023 5024$.effects.highlight = function(o) { 5025 return this.queue(function() { 5026 var elem = $(this), 5027 props = ['backgroundImage', 'backgroundColor', 'opacity'], 5028 mode = $.effects.setMode(elem, o.options.mode || 'show'), 5029 animation = { 5030 backgroundColor: elem.css('backgroundColor') 5031 }; 5032 5033 if (mode == 'hide') { 5034 animation.opacity = 0; 5035 } 5036 5037 $.effects.save(elem, props); 5038 elem 5039 .show() 5040 .css({ 5041 backgroundImage: 'none', 5042 backgroundColor: o.options.color || '#ffff99' 5043 }) 5044 .animate(animation, { 5045 queue: false, 5046 duration: o.duration, 5047 easing: o.options.easing, 5048 complete: function() { 5049 (mode == 'hide' && elem.hide()); 5050 $.effects.restore(elem, props); 5051 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); 5052 (o.callback && o.callback.apply(this, arguments)); 5053 elem.dequeue(); 5054 } 5055 }); 5056 }); 5057}; 5058 5059})(jQuery); 5060 5061(function( $, undefined ) { 5062 5063$.effects.pulsate = function(o) { 5064 return this.queue(function() { 5065 var elem = $(this), 5066 mode = $.effects.setMode(elem, o.options.mode || 'show'), 5067 times = ((o.options.times || 5) * 2) - 1, 5068 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2, 5069 isVisible = elem.is(':visible'), 5070 animateTo = 0; 5071 5072 if (!isVisible) { 5073 elem.css('opacity', 0).show(); 5074 animateTo = 1; 5075 } 5076 5077 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) { 5078 times--; 5079 } 5080 5081 for (var i = 0; i < times; i++) { 5082 elem.animate({ opacity: animateTo }, duration, o.options.easing); 5083 animateTo = (animateTo + 1) % 2; 5084 } 5085 5086 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() { 5087 if (animateTo == 0) { 5088 elem.hide(); 5089 } 5090 (o.callback && o.callback.apply(this, arguments)); 5091 }); 5092 5093 elem 5094 .queue('fx', function() { elem.dequeue(); }) 5095 .dequeue(); 5096 }); 5097}; 5098 5099})(jQuery); 5100 5101(function( $, undefined ) { 5102 5103$.effects.puff = function(o) { 5104 return this.queue(function() { 5105 var elem = $(this), 5106 mode = $.effects.setMode(elem, o.options.mode || 'hide'), 5107 percent = parseInt(o.options.percent, 10) || 150, 5108 factor = percent / 100, 5109 original = { height: elem.height(), width: elem.width() }; 5110 5111 $.extend(o.options, { 5112 fade: true, 5113 mode: mode, 5114 percent: mode == 'hide' ? percent : 100, 5115 from: mode == 'hide' 5116 ? original 5117 : { 5118 height: original.height * factor, 5119 width: original.width * factor 5120 } 5121 }); 5122 5123 elem.effect('scale', o.options, o.duration, o.callback); 5124 elem.dequeue(); 5125 }); 5126}; 5127 5128$.effects.scale = function(o) { 5129 5130 return this.queue(function() { 5131 5132 // Create element 5133 var el = $(this); 5134 5135 // Set options 5136 var options = $.extend(true, {}, o.options); 5137 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 5138 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent 5139 var direction = o.options.direction || 'both'; // Set default axis 5140 var origin = o.options.origin; // The origin of the scaling 5141 if (mode != 'effect') { // Set default origin and restore for show/hide 5142 options.origin = origin || ['middle','center']; 5143 options.restore = true; 5144 } 5145 var original = {height: el.height(), width: el.width()}; // Save original 5146 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state 5147 5148 // Adjust 5149 var factor = { // Set scaling factor 5150 y: direction != 'horizontal' ? (percent / 100) : 1, 5151 x: direction != 'vertical' ? (percent / 100) : 1 5152 }; 5153 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state 5154 5155 if (o.options.fade) { // Fade option to support puff 5156 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;}; 5157 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;}; 5158 }; 5159 5160 // Animation 5161 options.from = el.from; options.to = el.to; options.mode = mode; 5162 5163 // Animate 5164 el.effect('size', options, o.duration, o.callback); 5165 el.dequeue(); 5166 }); 5167 5168}; 5169 5170$.effects.size = function(o) { 5171 5172 return this.queue(function() { 5173 5174 // Create element 5175 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity']; 5176 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore 5177 var props2 = ['width','height','overflow']; // Copy for children 5178 var cProps = ['fontSize']; 5179 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; 5180 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; 5181 5182 // Set options 5183 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 5184 var restore = o.options.restore || false; // Default restore 5185 var scale = o.options.scale || 'both'; // Default scale mode 5186 var origin = o.options.origin; // The origin of the sizing 5187 var original = {height: el.height(), width: el.width()}; // Save original 5188 el.from = o.options.from || original; // Default from state 5189 el.to = o.options.to || original; // Default to state 5190 // Adjust 5191 if (origin) { // Calculate baseline shifts 5192 var baseline = $.effects.getBaseline(origin, original); 5193 el.from.top = (original.height - el.from.height) * baseline.y; 5194 el.from.left = (original.width - el.from.width) * baseline.x; 5195 el.to.top = (original.height - el.to.height) * baseline.y; 5196 el.to.left = (original.width - el.to.width) * baseline.x; 5197 }; 5198 var factor = { // Set scaling factor 5199 from: {y: el.from.height / original.height, x: el.from.width / original.width}, 5200 to: {y: el.to.height / original.height, x: el.to.width / original.width} 5201 }; 5202 if (scale == 'box' || scale == 'both') { // Scale the css box 5203 if (factor.from.y != factor.to.y) { // Vertical props scaling 5204 props = props.concat(vProps); 5205 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from); 5206 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to); 5207 }; 5208 if (factor.from.x != factor.to.x) { // Horizontal props scaling 5209 props = props.concat(hProps); 5210 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from); 5211 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to); 5212 }; 5213 }; 5214 if (scale == 'content' || scale == 'both') { // Scale the content 5215 if (factor.from.y != factor.to.y) { // Vertical props scaling 5216 props = props.concat(cProps); 5217 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from); 5218 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to); 5219 }; 5220 }; 5221 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show 5222 $.effects.createWrapper(el); // Create Wrapper 5223 el.css('overflow','hidden').css(el.from); // Shift 5224 5225 // Animate 5226 if (scale == 'content' || scale == 'both') { // Scale the children 5227 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size 5228 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins 5229 props2 = props.concat(vProps).concat(hProps); // Concat 5230 el.find("*[width]").each(function(){ 5231 var child = $(this); 5232 if (restore) $.effects.save(child, props2); 5233 var c_original = {height: child.height(), width: child.width()}; // Save original 5234 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x}; 5235 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x}; 5236 if (factor.from.y != factor.to.y) { // Vertical props scaling 5237 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from); 5238 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to); 5239 }; 5240 if (factor.from.x != factor.to.x) { // Horizontal props scaling 5241 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from); 5242 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to); 5243 }; 5244 child.css(child.from); // Shift children
5245 child.animate(child.to, o.duration, o.options.easing, function(){ 5246 if (restore) $.effects.restore(child, props2); // Restore children 5247 }); // Animate children 5248 }); 5249 }; 5250 5251 // Animate 5252 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 5253 if (el.to.opacity === 0) { 5254 el.css('opacity', el.from.opacity); 5255 } 5256 if(mode == 'hide') el.hide(); // Hide 5257 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore 5258 if(o.callback) o.callback.apply(this, arguments); // Callback 5259 el.dequeue(); 5260 }}); 5261 5262 }); 5263 5264}; 5265 5266})(jQuery); 5267 5268(function( $, undefined ) { 5269 5270$.effects.shake = function(o) { 5271 5272 return this.queue(function() { 5273 5274 // Create element 5275 var el = $(this), props = ['position','top','bottom','left','right']; 5276 5277 // Set options 5278 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 5279 var direction = o.options.direction || 'left'; // Default direction 5280 var distance = o.options.distance || 20; // Default distance 5281 var times = o.options.times || 3; // Default # of times 5282 var speed = o.duration || o.options.duration || 140; // Default speed per shake 5283 5284 // Adjust 5285 $.effects.save(el, props); el.show(); // Save & Show 5286 $.effects.createWrapper(el); // Create Wrapper 5287 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 5288 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 5289 5290 // Animation 5291 var animation = {}, animation1 = {}, animation2 = {}; 5292 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 5293 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2; 5294 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2; 5295 5296 // Animate 5297 el.animate(animation, speed, o.options.easing); 5298 for (var i = 1; i < times; i++) { // Shakes 5299 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing); 5300 }; 5301 el.animate(animation1, speed, o.options.easing). 5302 animate(animation, speed / 2, o.options.easing, function(){ // Last shake 5303 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 5304 if(o.callback) o.callback.apply(this, arguments); // Callback 5305 }); 5306 el.queue('fx', function() { el.dequeue(); }); 5307 el.dequeue(); 5308 }); 5309 5310}; 5311 5312})(jQuery); 5313 5314(function( $, undefined ) { 5315 5316$.effects.slide = function(o) { 5317 5318 return this.queue(function() { 5319 5320 // Create element 5321 var el = $(this), props = ['position','top','bottom','left','right']; 5322 5323 // Set options 5324 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode 5325 var direction = o.options.direction || 'left'; // Default Direction 5326 5327 // Adjust 5328 $.effects.save(el, props); el.show(); // Save & Show 5329 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 5330 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 5331 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 5332 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true})); 5333 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift 5334 5335 // Animation 5336 var animation = {}; 5337 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; 5338 5339 // Animate 5340 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 5341 if(mode == 'hide') el.hide(); // Hide 5342 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 5343 if(o.callback) o.callback.apply(this, arguments); // Callback 5344 el.dequeue(); 5345 }}); 5346 5347 }); 5348 5349}; 5350 5351})(jQuery); 5352 5353(function( $, undefined ) { 5354 5355$.effects.transfer = function(o) { 5356 return this.queue(function() { 5357 var elem = $(this), 5358 target = $(o.options.to), 5359 endPosition = target.offset(), 5360 animation = { 5361 top: endPosition.top, 5362 left: endPosition.left, 5363 height: target.innerHeight(), 5364 width: target.innerWidth() 5365 }, 5366 startPosition = elem.offset(),
5367 transfer = $('<div class="ui-effects-transfer"></div>') 5368 .appendTo(document.body) 5369 .addClass(o.options.className) 5370 .css({ 5371 top: startPosition.top, 5372 left: startPosition.left, 5373 height: elem.innerHeight(), 5374 width: elem.innerWidth(), 5375 position: 'absolute' 5376 }) 5377 .animate(animation, o.duration, o.options.easing, function() { 5378 transfer.remove(); 5379 (o.callback && o.callback.apply(elem[0], arguments)); 5380 elem.dequeue(); 5381 }); 5382 }); 5383}; 5384 5385})(jQuery); 5386 5387(function( $, undefined ) { 5388 5389$.widget( "ui.accordion", { 5390 options: { 5391 active: 0, 5392 animated: "slide", 5393 autoHeight: true, 5394 clearStyle: false, 5395 collapsible: false, 5396 event: "click", 5397 fillSpace: false, 5398 header: "> li > :first-child,> :not(li):even", 5399 icons: { 5400 header: "ui-icon-triangle-1-e", 5401 headerSelected: "ui-icon-triangle-1-s" 5402 }, 5403 navigation: false, 5404 navigationFilter: function() { 5405 return this.href.toLowerCase() === location.href.toLowerCase(); 5406 } 5407 }, 5408 5409 _create: function() { 5410 var self = this, 5411 options = self.options; 5412 5413 self.running = 0; 5414 5415 self.element 5416 .addClass( "ui-accordion ui-widget ui-helper-reset" ) 5417 // in lack of child-selectors in CSS 5418 // we need to mark top-LIs in a UL-accordion for some IE-fix 5419 .children( "li" ) 5420 .addClass( "ui-accordion-li-fix" ); 5421 5422 self.headers = self.element.find( options.header ) 5423 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ) 5424 .bind( "mouseenter.accordion", function() { 5425 if ( options.disabled ) { 5426 return; 5427 } 5428 $( this ).addClass( "ui-state-hover" ); 5429 }) 5430 .bind( "mouseleave.accordion", function() { 5431 if ( options.disabled ) { 5432 return; 5433 } 5434 $( this ).removeClass( "ui-state-hover" ); 5435 }) 5436 .bind( "focus.accordion", function() { 5437 if ( options.disabled ) { 5438 return; 5439 } 5440 $( this ).addClass( "ui-state-focus" ); 5441 }) 5442 .bind( "blur.accordion", function() { 5443 if ( options.disabled ) { 5444 return; 5445 } 5446 $( this ).removeClass( "ui-state-focus" ); 5447 }); 5448 5449 self.headers.next() 5450 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); 5451 5452 if ( options.navigation ) { 5453 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 ); 5454 if ( current.length ) { 5455 var header = current.closest( ".ui-accordion-header" ); 5456 if ( header.length ) { 5457 // anchor within header 5458 self.active = header; 5459 } else { 5460 // anchor within content 5461 self.active = current.closest( ".ui-accordion-content" ).prev(); 5462 } 5463 } 5464 } 5465 5466 self.active = self._findActive( self.active || options.active ) 5467 .addClass( "ui-state-default ui-state-active" ) 5468 .toggleClass( "ui-corner-all" ) 5469 .toggleClass( "ui-corner-top" ); 5470 self.active.next().addClass( "ui-accordion-content-active" ); 5471 5472 self._createIcons(); 5473 self.resize(); 5474 5475 // ARIA 5476 self.element.attr( "role", "tablist" ); 5477 5478 self.headers 5479 .attr( "role", "tab" ) 5480 .bind( "keydown.accordion", function( event ) { 5481 return self._keydown( event ); 5482 }) 5483 .next() 5484 .attr( "role", "tabpanel" ); 5485 5486 self.headers 5487 .not( self.active || "" ) 5488 .attr({ 5489 "aria-expanded": "false", 5490 "aria-selected": "false", 5491 tabIndex: -1 5492 }) 5493 .next() 5494 .hide(); 5495 5496 // make sure at least one header is in the tab order 5497 if ( !self.active.length ) { 5498 self.headers.eq( 0 ).attr( "tabIndex", 0 ); 5499 } else { 5500 self.active 5501 .attr({ 5502 "aria-expanded": "true", 5503 "aria-selected": "true", 5504 tabIndex: 0 5505 }); 5506 } 5507 5508 // only need links in tab order for Safari 5509 if ( !$.browser.safari ) { 5510 self.headers.find( "a" ).attr( "tabIndex", -1 ); 5511 } 5512 5513 if ( options.event ) { 5514 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) { 5515 self._clickHandler.call( self, event, this ); 5516 event.preventDefault(); 5517 }); 5518 } 5519 }, 5520 5521 _createIcons: function() { 5522 var options = this.options; 5523 if ( options.icons ) { 5524 $( "<span></span>" ) 5525 .addClass( "ui-icon " + options.icons.header ) 5526 .prependTo( this.headers ); 5527 this.active.children( ".ui-icon" ) 5528 .toggleClass(options.icons.header) 5529 .toggleClass(options.icons.headerSelected); 5530 this.element.addClass( "ui-accordion-icons" ); 5531 } 5532 }, 5533 5534 _destroyIcons: function() { 5535 this.headers.children( ".ui-icon" ).remove(); 5536 this.element.removeClass( "ui-accordion-icons" ); 5537 }, 5538 5539 destroy: function() { 5540 var options = this.options; 5541 5542 this.element 5543 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 5544 .removeAttr( "role" ); 5545 5546 this.headers 5547 .unbind( ".accordion" ) 5548 .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" ) 5549 .removeAttr( "role" ) 5550 .removeAttr( "aria-expanded" ) 5551 .removeAttr( "aria-selected" ) 5552 .removeAttr( "tabIndex" ); 5553 5554 this.headers.find( "a" ).removeAttr( "tabIndex" ); 5555 this._destroyIcons(); 5556 var contents = this.headers.next() 5557 .css( "display", "" ) 5558 .removeAttr( "role" ) 5559 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); 5560 if ( options.autoHeight || options.fillHeight ) { 5561 contents.css( "height", "" ); 5562 } 5563 5564 return $.Widget.prototype.destroy.call( this ); 5565 }, 5566 5567 _setOption: function( key, value ) { 5568 $.Widget.prototype._setOption.apply( this, arguments ); 5569 5570 if ( key == "active" ) { 5571 this.activate( value ); 5572 } 5573 if ( key == "icons" ) { 5574 this._destroyIcons(); 5575 if ( value ) { 5576 this._createIcons(); 5577 } 5578 } 5579 // #5332 - opacity doesn't cascade to positioned elements in IE 5580 // so we need to add the disabled class to the headers and panels 5581 if ( key == "disabled" ) { 5582 this.headers.add(this.headers.next()) 5583 [ value ? "addClass" : "removeClass" ]( 5584 "ui-accordion-disabled ui-state-disabled" ); 5585 } 5586 }, 5587 5588 _keydown: function( event ) { 5589 if ( this.options.disabled || event.altKey || event.ctrlKey ) { 5590 return; 5591 } 5592 5593 var keyCode = $.ui.keyCode,
5594 length = this.headers.length, 5595 currentIndex = this.headers.index( event.target ), 5596 toFocus = false; 5597 5598 switch ( event.keyCode ) { 5599 case keyCode.RIGHT: 5600 case keyCode.DOWN: 5601 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 5602 break; 5603 case keyCode.LEFT: 5604 case keyCode.UP: 5605 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 5606 break; 5607 case keyCode.SPACE: 5608 case keyCode.ENTER: 5609 this._clickHandler( { target: event.target }, event.target ); 5610 event.preventDefault(); 5611 } 5612 5613 if ( toFocus ) { 5614 $( event.target ).attr( "tabIndex", -1 ); 5615 $( toFocus ).attr( "tabIndex", 0 ); 5616 toFocus.focus(); 5617 return false; 5618 } 5619 5620 return true; 5621 }, 5622 5623 resize: function() { 5624 var options = this.options, 5625 maxHeight; 5626 5627 if ( options.fillSpace ) { 5628 if ( $.browser.msie ) { 5629 var defOverflow = this.element.parent().css( "overflow" ); 5630 this.element.parent().css( "overflow", "hidden"); 5631 } 5632 maxHeight = this.element.parent().height(); 5633 if ($.browser.msie) { 5634 this.element.parent().css( "overflow", defOverflow ); 5635 } 5636 5637 this.headers.each(function() { 5638 maxHeight -= $( this ).outerHeight( true ); 5639 }); 5640 5641 this.headers.next() 5642 .each(function() { 5643 $( this ).height( Math.max( 0, maxHeight - 5644 $( this ).innerHeight() + $( this ).height() ) ); 5645 }) 5646 .css( "overflow", "auto" ); 5647 } else if ( options.autoHeight ) { 5648 maxHeight = 0; 5649 this.headers.next() 5650 .each(function() { 5651 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 5652 }) 5653 .height( maxHeight ); 5654 } 5655 5656 return this; 5657 }, 5658 5659 activate: function( index ) { 5660 // TODO this gets called on init, changing the option without an explicit call for that 5661 this.options.active = index; 5662 // call clickHandler with custom event 5663 var active = this._findActive( index )[ 0 ]; 5664 this._clickHandler( { target: active }, active ); 5665 5666 return this; 5667 }, 5668 5669 _findActive: function( selector ) { 5670 return selector 5671 ? typeof selector === "number" 5672 ? this.headers.filter( ":eq(" + selector + ")" ) 5673 : this.headers.not( this.headers.not( selector ) ) 5674 : selector === false 5675 ? $( [] ) 5676 : this.headers.filter( ":eq(0)" ); 5677 }, 5678 5679 // TODO isn't event.target enough? why the separate target argument? 5680 _clickHandler: function( event, target ) { 5681 var options = this.options; 5682 if ( options.disabled ) { 5683 return; 5684 } 5685 5686 // called only when using activate(false) to close all parts programmatically 5687 if ( !event.target ) { 5688 if ( !options.collapsible ) { 5689 return; 5690 } 5691 this.active 5692 .removeClass( "ui-state-active ui-corner-top" ) 5693 .addClass( "ui-state-default ui-corner-all" ) 5694 .children( ".ui-icon" ) 5695 .removeClass( options.icons.headerSelected ) 5696 .addClass( options.icons.header ); 5697 this.active.next().addClass( "ui-accordion-content-active" ); 5698 var toHide = this.active.next(), 5699 data = { 5700 options: options, 5701 newHeader: $( [] ), 5702 oldHeader: options.active, 5703 newContent: $( [] ), 5704 oldContent: toHide 5705 }, 5706 toShow = ( this.active = $( [] ) ); 5707 this._toggle( toShow, toHide, data ); 5708 return; 5709 } 5710 5711 // get the click target 5712 var clicked = $( event.currentTarget || target ), 5713 clickedIsActive = clicked[0] === this.active[0]; 5714 5715 // TODO the option is changed, is that correct? 5716 // TODO if it is correct, shouldn't that happen after determining that the click is valid? 5717 options.active = options.collapsible && clickedIsActive ? 5718 false : 5719 this.headers.index( clicked ); 5720 5721 // if animations are still active, or the active header is the target, ignore click 5722 if ( this.running || ( !options.collapsible && clickedIsActive ) ) { 5723 return; 5724 } 5725 5726 // find elements to show and hide 5727 var active = this.active, 5728 toShow = clicked.next(), 5729 toHide = this.active.next(), 5730 data = { 5731 options: options, 5732 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, 5733 oldHeader: this.active, 5734 newContent: clickedIsActive && options.collapsible ? $([]) : toShow, 5735 oldContent: toHide 5736 }, 5737 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); 5738 5739 // when the call to ._toggle() comes after the class changes 5740 // it causes a very odd bug in IE 8 (see #6720) 5741 this.active = clickedIsActive ? $([]) : clicked; 5742 this._toggle( toShow, toHide, data, clickedIsActive, down ); 5743 5744 // switch classes 5745 active 5746 .removeClass( "ui-state-active ui-corner-top" ) 5747 .addClass( "ui-state-default ui-corner-all" ) 5748 .children( ".ui-icon" ) 5749 .removeClass( options.icons.headerSelected )
5750 .addClass( options.icons.header ); 5751 if ( !clickedIsActive ) { 5752 clicked 5753 .removeClass( "ui-state-default ui-corner-all" ) 5754 .addClass( "ui-state-active ui-corner-top" ) 5755 .children( ".ui-icon" ) 5756 .removeClass( options.icons.header ) 5757 .addClass( options.icons.headerSelected ); 5758 clicked 5759 .next() 5760 .addClass( "ui-accordion-content-active" ); 5761 } 5762 5763 return; 5764 }, 5765 5766 _toggle: function( toShow, toHide, data, clickedIsActive, down ) { 5767 var self = this, 5768 options = self.options; 5769 5770 self.toShow = toShow; 5771 self.toHide = toHide; 5772 self.data = data; 5773 5774 var complete = function() { 5775 if ( !self ) { 5776 return; 5777 } 5778 return self._completed.apply( self, arguments ); 5779 }; 5780 5781 // trigger changestart event 5782 self._trigger( "changestart", null, self.data ); 5783 5784 // count elements to animate 5785 self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); 5786 5787 if ( options.animated ) { 5788 var animOptions = {}; 5789 5790 if ( options.collapsible && clickedIsActive ) { 5791 animOptions = { 5792 toShow: $( [] ), 5793 toHide: toHide, 5794 complete: complete, 5795 down: down, 5796 autoHeight: options.autoHeight || options.fillSpace 5797 }; 5798 } else { 5799 animOptions = { 5800 toShow: toShow, 5801 toHide: toHide, 5802 complete: complete, 5803 down: down, 5804 autoHeight: options.autoHeight || options.fillSpace 5805 }; 5806 } 5807 5808 if ( !options.proxied ) { 5809 options.proxied = options.animated; 5810 } 5811 5812 if ( !options.proxiedDuration ) { 5813 options.proxiedDuration = options.duration; 5814 } 5815 5816 options.animated = $.isFunction( options.proxied ) ? 5817 options.proxied( animOptions ) : 5818 options.proxied; 5819 5820 options.duration = $.isFunction( options.proxiedDuration ) ? 5821 options.proxiedDuration( animOptions ) : 5822 options.proxiedDuration; 5823 5824 var animations = $.ui.accordion.animations, 5825 duration = options.duration, 5826 easing = options.animated; 5827 5828 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) { 5829 easing = "slide"; 5830 } 5831 if ( !animations[ easing ] ) { 5832 animations[ easing ] = function( options ) { 5833 this.slide( options, { 5834 easing: easing, 5835 duration: duration || 700 5836 }); 5837 }; 5838 } 5839 5840 animations[ easing ]( animOptions ); 5841 } else { 5842 if ( options.collapsible && clickedIsActive ) { 5843 toShow.toggle(); 5844 } else { 5845 toHide.hide(); 5846 toShow.show(); 5847 } 5848 5849 complete( true ); 5850 } 5851 5852 // TODO assert that the blur and focus triggers are really necessary, remove otherwise 5853 toHide.prev() 5854 .attr({ 5855 "aria-expanded": "false", 5856 "aria-selected": "false", 5857 tabIndex: -1 5858 }) 5859 .blur(); 5860 toShow.prev() 5861 .attr({ 5862 "aria-expanded": "true", 5863 "aria-selected": "true", 5864 tabIndex: 0 5865 }) 5866 .focus(); 5867 }, 5868 5869 _completed: function( cancel ) { 5870 this.running = cancel ? 0 : --this.running; 5871 if ( this.running ) { 5872 return; 5873 } 5874 5875 if ( this.options.clearStyle ) { 5876 this.toShow.add( this.toHide ).css({ 5877 height: "", 5878 overflow: "" 5879 }); 5880 } 5881 5882 // other classes are removed before the animation; this one needs to stay until completed 5883 this.toHide.removeClass( "ui-accordion-content-active" ); 5884 // Work around for rendering bug in IE (#5421) 5885 if ( this.toHide.length ) { 5886 this.toHide.parent()[0].className = this.toHide.parent()[0].className; 5887 } 5888 5889 this._trigger( "change", null, this.data ); 5890 } 5891}); 5892 5893$.extend( $.ui.accordion, { 5894 version: "@VERSION", 5895 animations: { 5896 slide: function( options, additions ) { 5897 options = $.extend({ 5898 easing: "swing", 5899 duration: 300 5900 }, options, additions ); 5901 if ( !options.toHide.size() ) { 5902 options.toShow.animate({ 5903 height: "show", 5904 paddingTop: "show", 5905 paddingBottom: "show" 5906 }, options ); 5907 return; 5908 } 5909 if ( !options.toShow.size() ) { 5910 options.toHide.animate({ 5911 height: "hide", 5912 paddingTop: "hide", 5913 paddingBottom: "hide" 5914 }, options ); 5915 return; 5916 } 5917 var overflow = options.toShow.css( "overflow" ), 5918 percentDone = 0, 5919 showProps = {}, 5920 hideProps = {}, 5921 fxAttrs = [ "height", "paddingTop", "paddingBottom" ], 5922 originalWidth; 5923 // fix width before calculating height of hidden element 5924 var s = options.toShow; 5925 originalWidth = s[0].style.width; 5926 s.width( s.parent().width() 5927 - parseFloat( s.css( "paddingLeft" ) ) 5928 - parseFloat( s.css( "paddingRight" ) ) 5929 - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 ) 5930 - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) ); 5931 5932 $.each( fxAttrs, function( i, prop ) { 5933 hideProps[ prop ] = "hide"; 5934 5935 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ); 5936 showProps[ prop ] = { 5937 value: parts[ 1 ], 5938 unit: parts[ 2 ] || "px" 5939 }; 5940 }); 5941 options.toShow.css({ height: 0, overflow: "hidden" }).show(); 5942 options.toHide 5943 .filter( ":hidden" ) 5944 .each( options.complete ) 5945 .end() 5946 .filter( ":visible" ) 5947 .animate( hideProps, { 5948 step: function( now, settings ) { 5949 // only calculate the percent when animating height 5950 // IE gets very inconsistent results when animating elements 5951 // with small values, which is common for padding 5952 if ( settings.prop == "height" ) { 5953 percentDone = ( settings.end - settings.start === 0 ) ? 0 : 5954 ( settings.now - settings.start ) / ( settings.end - settings.start ); 5955 } 5956 5957 options.toShow[ 0 ].style[ settings.prop ] = 5958 ( percentDone * showProps[ settings.prop ].value ) 5959 + showProps[ settings.prop ].unit; 5960 }, 5961 duration: options.duration, 5962 easing: options.easing, 5963 complete: function() { 5964 if ( !options.autoHeight ) { 5965 options.toShow.css( "height", "" ); 5966 } 5967 options.toShow.css({ 5968 width: originalWidth, 5969 overflow: overflow 5970 });
5971 options.complete(); 5972 } 5973 }); 5974 }, 5975 bounceslide: function( options ) { 5976 this.slide( options, { 5977 easing: options.down ? "easeOutBounce" : "swing", 5978 duration: options.down ? 1000 : 200 5979 }); 5980 } 5981 } 5982}); 5983 5984})( jQuery ); 5985 5986(function( $, undefined ) { 5987 5988// used to prevent race conditions with remote data sources 5989var requestIndex = 0; 5990 5991$.widget( "ui.autocomplete", { 5992 options: { 5993 appendTo: "body", 5994 autoFocus: false, 5995 delay: 300, 5996 minLength: 1, 5997 position: { 5998 my: "left top", 5999 at: "left bottom", 6000 collision: "none" 6001 }, 6002 source: null 6003 }, 6004 6005 pending: 0, 6006 6007 _create: function() { 6008 var self = this, 6009 doc = this.element[ 0 ].ownerDocument, 6010 suppressKeyPress; 6011 this.isMultiLine = this.element.is( "textarea" ); 6012 6013 this.element 6014 .addClass( "ui-autocomplete-input" ) 6015 .attr( "autocomplete", "off" ) 6016 // TODO verify these actually work as intended 6017 .attr({ 6018 role: "textbox", 6019 "aria-autocomplete": "list", 6020 "aria-haspopup": "true" 6021 }) 6022 .bind( "keydown.autocomplete", function( event ) { 6023 if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) { 6024 return; 6025 } 6026 6027 suppressKeyPress = false; 6028 var keyCode = $.ui.keyCode; 6029 switch( event.keyCode ) { 6030 case keyCode.PAGE_UP: 6031 self._move( "previousPage", event ); 6032 break; 6033 case keyCode.PAGE_DOWN: 6034 self._move( "nextPage", event ); 6035 break; 6036 case keyCode.UP: 6037 self._keyEvent( "previous", event ); 6038 break; 6039 case keyCode.DOWN: 6040 self._keyEvent( "next", event ); 6041 break; 6042 case keyCode.ENTER: 6043 case keyCode.NUMPAD_ENTER: 6044 // when menu is open and has focus 6045 if ( self.menu.active ) { 6046 // #6055 - Opera still allows the keypress to occur 6047 // which causes forms to submit 6048 suppressKeyPress = true; 6049 event.preventDefault(); 6050 } 6051 //passthrough - ENTER and TAB both select the current element 6052 case keyCode.TAB: 6053 if ( !self.menu.active ) { 6054 return; 6055 } 6056 self.menu.select( event ); 6057 break; 6058 case keyCode.ESCAPE: 6059 self.element.val( self.term ); 6060 self.close( event ); 6061 break; 6062 default: 6063 // keypress is triggered before the input value is changed 6064 clearTimeout( self.searching ); 6065 self.searching = setTimeout(function() { 6066 // only search if the value has changed 6067 if ( self.term != self.element.val() ) { 6068 self.selectedItem = null; 6069 self.search( null, event ); 6070 } 6071 }, self.options.delay ); 6072 break; 6073 } 6074 }) 6075 .bind( "keypress.autocomplete", function( event ) { 6076 if ( suppressKeyPress ) { 6077 suppressKeyPress = false; 6078 event.preventDefault(); 6079 } 6080 }) 6081 .bind( "focus.autocomplete", function() { 6082 if ( self.options.disabled ) { 6083 return; 6084 } 6085 6086 self.selectedItem = null; 6087 self.previous = self.element.val(); 6088 }) 6089 .bind( "blur.autocomplete", function( event ) { 6090 if ( self.options.disabled ) { 6091 return; 6092 } 6093 6094 clearTimeout( self.searching ); 6095 // clicks on the menu (or a button to trigger a search) will cause a blur event 6096 self.closing = setTimeout(function() { 6097 self.close( event ); 6098 self._change( event ); 6099 }, 150 ); 6100 }); 6101 this._initSource(); 6102 this.menu = $( "<ul></ul>" ) 6103 .addClass( "ui-autocomplete" ) 6104 .appendTo( $( this.options.appendTo || "body", doc )[0] ) 6105 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) 6106 .mousedown(function( event ) { 6107 // clicking on the scrollbar causes focus to shift to the body 6108 // but we can't detect a mouseup or a click immediately afterward 6109 // so we have to track the next mousedown and close the menu if 6110 // the user clicks somewhere outside of the autocomplete 6111 var menuElement = self.menu.element[ 0 ]; 6112 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 6113 setTimeout(function() { 6114 $( document ).one( 'mousedown', function( event ) { 6115 if ( event.target !== self.element[ 0 ] && 6116 event.target !== menuElement && 6117 !$.ui.contains( menuElement, event.target ) ) { 6118 self.close(); 6119 } 6120 });
6121 }, 1 ); 6122 } 6123 6124 // use another timeout to make sure the blur-event-handler on the input was already triggered 6125 setTimeout(function() { 6126 clearTimeout( self.closing ); 6127 }, 13); 6128 }) 6129 .menu({ 6130 focus: function( event, ui ) { 6131 var item = ui.item.data( "item.autocomplete" ); 6132 if ( false !== self._trigger( "focus", event, { item: item } ) ) { 6133 // use value to match what will end up in the input, if it was a key event 6134 if ( /^key/.test(event.originalEvent.type) ) { 6135 self.element.val( item.value ); 6136 } 6137 } 6138 }, 6139 selected: function( event, ui ) { 6140 var item = ui.item.data( "item.autocomplete" ), 6141 previous = self.previous; 6142 6143 // only trigger when focus was lost (click on menu) 6144 if ( self.element[0] !== doc.activeElement ) { 6145 self.element.focus(); 6146 self.previous = previous; 6147 // #6109 - IE triggers two focus events and the second 6148 // is asynchronous, so we need to reset the previous 6149 // term synchronously and asynchronously :-( 6150 setTimeout(function() { 6151 self.previous = previous; 6152 self.selectedItem = item; 6153 }, 1); 6154 } 6155 6156 if ( false !== self._trigger( "select", event, { item: item } ) ) { 6157 self.element.val( item.value ); 6158 } 6159 // reset the term after the select event 6160 // this allows custom select handling to work properly 6161 self.term = self.element.val(); 6162 6163 self.close( event ); 6164 self.selectedItem = item; 6165 }, 6166 blur: function( event, ui ) { 6167 // don't set the value of the text field if it's already correct 6168 // this prevents moving the cursor unnecessarily 6169 if ( self.menu.element.is(":visible") && 6170 ( self.element.val() !== self.term ) ) { 6171 self.element.val( self.term ); 6172 } 6173 } 6174 }) 6175 .css('zindex', this.element.css('zindex') + 1 ) 6176 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 6177 .css({ top: 0, left: 0 }) 6178 .hide() 6179 .data( "menu" ); 6180 if ( $.fn.bgiframe ) { 6181 this.menu.element.bgiframe(); 6182 } 6183 // turning off autocomplete prevents the browser from remembering the 6184 // value when navigating through history, so we re-enable autocomplete 6185 // if the page is unloaded before the widget is destroyed. #7790 6186 self.beforeunloadHandler = function() { 6187 self.element.removeAttr( "autocomplete" ); 6188 }; 6189 $( window ).bind( "beforeunload", self.beforeunloadHandler ); 6190 }, 6191 6192 destroy: function() { 6193 this.element 6194 .removeClass( "ui-autocomplete-input" ) 6195 .removeAttr( "autocomplete" ) 6196 .removeAttr( "role" ) 6197 .removeAttr( "aria-autocomplete" ) 6198 .removeAttr( "aria-haspopup" ); 6199 this.menu.element.remove(); 6200 $( window ).unbind( "beforeunload", this.beforeunloadHandler ); 6201 $.Widget.prototype.destroy.call( this ); 6202 }, 6203 6204 _setOption: function( key, value ) { 6205 $.Widget.prototype._setOption.apply( this, arguments ); 6206 if ( key === "source" ) { 6207 this._initSource(); 6208 } 6209 if ( key === "appendTo" ) { 6210 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) 6211 } 6212 if ( key === "disabled" && value && this.xhr ) { 6213 this.xhr.abort(); 6214 } 6215 }, 6216 6217 _initSource: function() { 6218 var self = this, 6219 array, 6220 url; 6221 if ( $.isArray(this.options.source) ) { 6222 array = this.options.source; 6223 this.source = function( request, response ) { 6224 response( $.ui.autocomplete.filter(array, request.term) ); 6225 }; 6226 } else if ( typeof this.options.source === "string" ) { 6227 url = this.options.source; 6228 this.source = function( request, response ) { 6229 if ( self.xhr ) { 6230 self.xhr.abort(); 6231 } 6232 self.xhr = $.ajax({ 6233 url: url, 6234 data: request, 6235 dataType: "json", 6236 success: function( data, status ) { 6237 response( data ); 6238 }, 6239 error: function() { 6240 response( [] ); 6241 } 6242 }); 6243 }; 6244 } else { 6245 this.source = this.options.source; 6246 } 6247 }, 6248 6249 search: function( value, event ) { 6250 value = value != null ? value : this.element.val(); 6251 6252 // always save the actual value, not the one passed as an argument 6253 this.term = this.element.val(); 6254 6255 if ( value.length < this.options.minLength ) { 6256 return this.close( event ); 6257 } 6258 6259 clearTimeout( this.closing ); 6260 if ( this._trigger( "search", event ) === false ) { 6261 return; 6262 } 6263 6264 return this._search( value ); 6265 }, 6266 6267 _search: function( value ) { 6268 this.pending++; 6269 this.element.addClass( "ui-autocomplete-loading" ); 6270 6271 this.source( { term: value }, this._response() ); 6272 }, 6273 6274 _response: function() { 6275 var that = this, 6276 index = ++requestIndex; 6277 6278 return function( content ) { 6279 if ( index === requestIndex ) { 6280 that.__response( content ); 6281 } 6282 6283 that.pending--; 6284 if ( !that.pending ) { 6285 that.element.removeClass( "ui-autocomplete-loading" ); 6286 } 6287 }; 6288 }, 6289 6290 __response: function( content ) { 6291 if ( !this.options.disabled && content && content.length ) { 6292 content = this._normalize( content ); 6293 this._suggest( content ); 6294 this._trigger( "open" ); 6295 } else { 6296 this.close(); 6297 } 6298 }, 6299 6300 close: function( event ) { 6301 clearTimeout( this.closing ); 6302 if ( this.menu.element.is(":visible") ) { 6303 this.menu.element.hide(); 6304 this.menu.deactivate(); 6305 this._trigger( "close", event ); 6306 } 6307 }, 6308 6309 _change: function( event ) { 6310 if ( this.previous !== this.element.val() ) { 6311 this._trigger( "change", event, { item: this.selectedItem } ); 6312 } 6313 }, 6314 6315 _normalize: function( items ) { 6316 // assume all items have the right format when the first item is complete 6317 if ( items.length && items[0].label && items[0].value ) { 6318 return items; 6319 } 6320 return $.map( items, function(item) { 6321 if ( typeof item === "string" ) { 6322 return { 6323 label: item, 6324 value: item 6325 }; 6326 } 6327 return $.extend({ 6328 label: item.label || item.value, 6329 value: item.value || item.label 6330 }, item ); 6331 }); 6332 }, 6333 6334 _suggest: function( items ) { 6335 var ul = this.menu.element 6336 .empty() 6337 .css('zindex', this.element.css('zindex') + 1 ); 6338 this._renderMenu( ul, items ); 6339 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate 6340 this.menu.deactivate(); 6341 this.menu.refresh();
6342 6343 // size and position menu 6344 ul.show(); 6345 this._resizeMenu(); 6346 ul.position( $.extend({ 6347 of: this.element 6348 }, this.options.position )); 6349 6350 if ( this.options.autoFocus ) { 6351 this.menu.next( new $.Event("mouseover") ); 6352 } 6353 }, 6354 6355 _resizeMenu: function() { 6356 var ul = this.menu.element; 6357 ul.outerWidth( Math.max( 6358 // Firefox wraps long text (possibly a rounding bug) 6359 // so we add 1px to avoid the wrapping (#7513) 6360 ul.width( "" ).outerWidth() + 1, 6361 this.element.outerWidth() 6362 ) ); 6363 }, 6364 6365 _renderMenu: function( ul, items ) { 6366 var self = this; 6367 $.each( items, function( index, item ) { 6368 self._renderItem( ul, item ); 6369 }); 6370 }, 6371 6372 _renderItem: function( ul, item) { 6373 return $( "<li></li>" ) 6374 .data( "item.autocomplete", item ) 6375 .append( $( "<a></a>" ).text( item.label ) ) 6376 .appendTo( ul ); 6377 }, 6378 6379 _move: function( direction, event ) { 6380 if ( !this.menu.element.is(":visible") ) { 6381 this.search( null, event ); 6382 return; 6383 } 6384 if ( this.menu.first() && /^previous/.test(direction) || 6385 this.menu.last() && /^next/.test(direction) ) { 6386 this.element.val( this.term ); 6387 this.menu.deactivate(); 6388 return; 6389 } 6390 this.menu[ direction ]( event ); 6391 }, 6392 6393 widget: function() { 6394 return this.menu.element; 6395 }, 6396 _keyEvent: function( keyEvent, event ) { 6397 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6398 this._move( keyEvent, event ); 6399 6400 // prevents moving cursor to beginning/end of the text field in some browsers 6401 event.preventDefault(); 6402 } 6403 } 6404}); 6405 6406$.extend( $.ui.autocomplete, { 6407 escapeRegex: function( value ) { 6408 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 6409 }, 6410 filter: function(array, term) { 6411 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); 6412 return $.grep( array, function(value) { 6413 return matcher.test( value.label || value.value || value ); 6414 }); 6415 } 6416}); 6417 6418}( jQuery )); 6419 6420/* 6421 * jQuery UI Menu (not officially released) 6422 * 6423 * This widget isn't yet finished and the API is subject to change. We plan to finish 6424 * it for the next release. You're welcome to give it a try anyway and give us feedback, 6425 * as long as you're okay with migrating your code later on. We can help with that, too. 6426 * 6427 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 6428 * Dual licensed under the MIT or GPL Version 2 licenses. 6429 * http://jquery.org/license 6430 * 6431 * http://docs.jquery.com/UI/Menu 6432 * 6433 * Depends: 6434 * jquery.ui.core.js 6435 * jquery.ui.widget.js 6436 */ 6437(function($) { 6438 6439$.widget("ui.menu", { 6440 _create: function() { 6441 var self = this; 6442 this.element 6443 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") 6444 .attr({ 6445 role: "listbox", 6446 "aria-activedescendant": "ui-active-menuitem" 6447 }) 6448 .click(function( event ) { 6449 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { 6450 return; 6451 } 6452 // temporary 6453 event.preventDefault(); 6454 self.select( event ); 6455 }); 6456 this.refresh(); 6457 }, 6458 6459 refresh: function() { 6460 var self = this; 6461 6462 // don't refresh list items that are already adapted 6463 var items = this.element.children("li:not(.ui-menu-item):has(a)") 6464 .addClass("ui-menu-item") 6465 .attr("role", "menuitem"); 6466 6467 items.children("a") 6468 .addClass("ui-corner-all") 6469 .attr("tabindex", -1) 6470 // mouseenter doesn't work with event delegation 6471 .mouseenter(function( event ) { 6472 self.activate( event, $(this).parent() ); 6473 }) 6474 .mouseleave(function() { 6475 self.deactivate(); 6476 }); 6477 }, 6478 6479 activate: function( event, item ) { 6480 this.deactivate(); 6481 if (this.hasScroll()) { 6482 var offset = item.offset().top - this.element.offset().top, 6483 scroll = this.element.scrollTop(), 6484 elementHeight = this.element.height(); 6485 if (offset < 0) { 6486 this.element.scrollTop( scroll + offset); 6487 } else if (offset >= elementHeight) { 6488 this.element.scrollTop( scroll + offset - elementHeight + item.height()); 6489 } 6490 } 6491 this.active = item.eq(0) 6492 .children("a") 6493 .addClass("ui-state-hover") 6494 .attr("id", "ui-active-menuitem") 6495 .end(); 6496 this._trigger("focus", event, { item: item });
6497 }, 6498 6499 deactivate: function() { 6500 if (!this.active) { return; } 6501 6502 this.active.children("a") 6503 .removeClass("ui-state-hover") 6504 .removeAttr("id"); 6505 this._trigger("blur"); 6506 this.active = null; 6507 }, 6508 6509 next: function(event) { 6510 this.move("next", ".ui-menu-item:first", event); 6511 }, 6512 6513 previous: function(event) { 6514 this.move("prev", ".ui-menu-item:last", event); 6515 }, 6516 6517 first: function() { 6518 return this.active && !this.active.prevAll(".ui-menu-item").length; 6519 }, 6520 6521 last: function() { 6522 return this.active && !this.active.nextAll(".ui-menu-item").length; 6523 }, 6524 6525 move: function(direction, edge, event) { 6526 if (!this.active) { 6527 this.activate(event, this.element.children(edge)); 6528 return; 6529 } 6530 var next = this.active[direction + "All"](".ui-menu-item").eq(0); 6531 if (next.length) { 6532 this.activate(event, next); 6533 } else { 6534 this.activate(event, this.element.children(edge)); 6535 } 6536 }, 6537 6538 // TODO merge with previousPage 6539 nextPage: function(event) { 6540 if (this.hasScroll()) { 6541 // TODO merge with no-scroll-else 6542 if (!this.active || this.last()) { 6543 this.activate(event, this.element.children(".ui-menu-item:first")); 6544 return; 6545 } 6546 var base = this.active.offset().top, 6547 height = this.element.height(), 6548 result = this.element.children(".ui-menu-item").filter(function() { 6549 var close = $(this).offset().top - base - height + $(this).height(); 6550 // TODO improve approximation 6551 return close < 10 && close > -10; 6552 }); 6553 6554 // TODO try to catch this earlier when scrollTop indicates the last page anyway 6555 if (!result.length) { 6556 result = this.element.children(".ui-menu-item:last"); 6557 } 6558 this.activate(event, result); 6559 } else { 6560 this.activate(event, this.element.children(".ui-menu-item") 6561 .filter(!this.active || this.last() ? ":first" : ":last")); 6562 } 6563 }, 6564 6565 // TODO merge with nextPage 6566 previousPage: function(event) { 6567 if (this.hasScroll()) { 6568 // TODO merge with no-scroll-else 6569 if (!this.active || this.first()) { 6570 this.activate(event, this.element.children(".ui-menu-item:last")); 6571 return; 6572 } 6573 6574 var base = this.active.offset().top, 6575 height = this.element.height(), 6576 result = this.element.children(".ui-menu-item").filter(function() { 6577 var close = $(this).offset().top - base + height - $(this).height(); 6578 // TODO improve approximation 6579 return close < 10 && close > -10; 6580 }); 6581 6582 // TODO try to catch this earlier when scrollTop indicates the last page anyway 6583 if (!result.length) { 6584 result = this.element.children(".ui-menu-item:first"); 6585 } 6586 this.activate(event, result); 6587 } else { 6588 this.activate(event, this.element.children(".ui-menu-item") 6589 .filter(!this.active || this.first() ? ":last" : ":first")); 6590 } 6591 }, 6592 6593 hasScroll: function() { 6594 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); 6595 }, 6596 6597 select: function( event ) { 6598 this._trigger("selected", event, { item: this.active }); 6599 } 6600}); 6601 6602}(jQuery)); 6603 6604(function( $, undefined ) { 6605 6606var lastActive, startXPos, startYPos, clickDragged, 6607 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 6608 stateClasses = "ui-state-hover ui-state-active ", 6609 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", 6610 formResetHandler = function() { 6611 var buttons = $( this ).find( ":ui-button" ); 6612 setTimeout(function() { 6613 buttons.button( "refresh" ); 6614 }, 1 ); 6615 }, 6616 radioGroup = function( radio ) { 6617 var name = radio.name, 6618 form = radio.form, 6619 radios = $( [] ); 6620 if ( name ) { 6621 if ( form ) { 6622 radios = $( form ).find( "[name='" + name + "']" ); 6623 } else { 6624 radios = $( "[name='" + name + "']", radio.ownerDocument ) 6625 .filter(function() { 6626 return !this.form; 6627 }); 6628 } 6629 } 6630 return radios; 6631 }; 6632 6633$.widget( "ui.button", { 6634 options: { 6635 disabled: null, 6636 text: true, 6637 label: null, 6638 icons: { 6639 primary: null, 6640 secondary: null 6641 } 6642 }, 6643 _create: function() { 6644 this.element.closest( "form" ) 6645 .unbind( "reset.button" ) 6646 .bind( "reset.button", formResetHandler ); 6647 6648 if ( typeof this.options.disabled !== "boolean" ) { 6649 this.options.disabled = !!this.element.propAttr( "disabled" ); 6650 } else { 6651 this.element.propAttr( "disabled", this.options.disabled ); 6652 } 6653 6654 this._determineButtonType(); 6655 this.hasTitle = !!this.buttonElement.attr( "title" ); 6656 6657 var self = this, 6658 options = this.options, 6659 toggleButton = this.type === "checkbox" || this.type === "radio", 6660 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ), 6661 focusClass = "ui-state-focus"; 6662 6663 if ( options.label === null ) { 6664 options.label = this.buttonElement.html(); 6665 } 6666 6667 this.buttonElement 6668 .addClass( baseClasses ) 6669 .attr( "role", "button" ) 6670 .bind( "mouseenter.button", function() { 6671 if ( options.disabled ) { 6672 return; 6673 } 6674 $( this ).addClass( "ui-state-hover" ); 6675 if ( this === lastActive ) { 6676 $( this ).addClass( "ui-state-active" ); 6677 } 6678 }) 6679 .bind( "mouseleave.button", function() { 6680 if ( options.disabled ) { 6681 return; 6682 } 6683 $( this ).removeClass( hoverClass ); 6684 }) 6685 .bind( "click.button", function( event ) { 6686 if ( options.disabled ) { 6687 event.preventDefault(); 6688 event.stopImmediatePropagation(); 6689 } 6690 }); 6691 6692 this.element 6693 .bind( "focus.button", function() { 6694 // no need to check disabled, focus won't be triggered anyway 6695 self.buttonElement.addClass( focusClass ); 6696 }) 6697 .bind( "blur.button", function() { 6698 self.buttonElement.removeClass( focusClass ); 6699 }); 6700 6701 if ( toggleButton ) { 6702 this.element.bind( "change.button", function() { 6703 if ( clickDragged ) { 6704 return; 6705 } 6706 self.refresh();
6707 }); 6708 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag 6709 // prevents issue where button state changes but checkbox/radio checked state 6710 // does not in Firefox (see ticket #6970) 6711 this.buttonElement 6712 .bind( "mousedown.button", function( event ) { 6713 if ( options.disabled ) { 6714 return; 6715 } 6716 clickDragged = false; 6717 startXPos = event.pageX; 6718 startYPos = event.pageY; 6719 }) 6720 .bind( "mouseup.button", function( event ) { 6721 if ( options.disabled ) { 6722 return; 6723 } 6724 if ( startXPos !== event.pageX || startYPos !== event.pageY ) { 6725 clickDragged = true; 6726 } 6727 }); 6728 } 6729 6730 if ( this.type === "checkbox" ) { 6731 this.buttonElement.bind( "click.button", function() { 6732 if ( options.disabled || clickDragged ) { 6733 return false; 6734 } 6735 $( this ).toggleClass( "ui-state-active" ); 6736 self.buttonElement.attr( "aria-pressed", self.element[0].checked ); 6737 }); 6738 } else if ( this.type === "radio" ) { 6739 this.buttonElement.bind( "click.button", function() { 6740 if ( options.disabled || clickDragged ) { 6741 return false; 6742 } 6743 $( this ).addClass( "ui-state-active" ); 6744 self.buttonElement.attr( "aria-pressed", "true" ); 6745 6746 var radio = self.element[ 0 ]; 6747 radioGroup( radio ) 6748 .not( radio ) 6749 .map(function() { 6750 return $( this ).button( "widget" )[ 0 ]; 6751 }) 6752 .removeClass( "ui-state-active" ) 6753 .attr( "aria-pressed", "false" ); 6754 }); 6755 } else { 6756 this.buttonElement 6757 .bind( "mousedown.button", function() { 6758 if ( options.disabled ) { 6759 return false; 6760 } 6761 $( this ).addClass( "ui-state-active" ); 6762 lastActive = this; 6763 $( document ).one( "mouseup", function() { 6764 lastActive = null; 6765 }); 6766 }) 6767 .bind( "mouseup.button", function() { 6768 if ( options.disabled ) { 6769 return false; 6770 } 6771 $( this ).removeClass( "ui-state-active" ); 6772 }) 6773 .bind( "keydown.button", function(event) { 6774 if ( options.disabled ) { 6775 return false; 6776 } 6777 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) { 6778 $( this ).addClass( "ui-state-active" ); 6779 } 6780 }) 6781 .bind( "keyup.button", function() { 6782 $( this ).removeClass( "ui-state-active" ); 6783 }); 6784 6785 if ( this.buttonElement.is("a") ) { 6786 this.buttonElement.keyup(function(event) { 6787 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6788 // TODO pass through original event correctly (just as 2nd argument doesn't work) 6789 $( this ).click(); 6790 } 6791 }); 6792 } 6793 } 6794 6795 // TODO: pull out $.Widget's handling for the disabled option into 6796 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can 6797 // be overridden by individual plugins 6798 this._setOption( "disabled", options.disabled ); 6799 this._resetButton(); 6800 }, 6801 6802 _determineButtonType: function() { 6803 6804 if ( this.element.is(":checkbox") ) { 6805 this.type = "checkbox"; 6806 } else if ( this.element.is(":radio") ) { 6807 this.type = "radio"; 6808 } else if ( this.element.is("input") ) { 6809 this.type = "input"; 6810 } else { 6811 this.type = "button"; 6812 } 6813 6814 if ( this.type === "checkbox" || this.type === "radio" ) { 6815 // we don't search against the document in case the element 6816 // is disconnected from the DOM 6817 var ancestor = this.element.parents().filter(":last"), 6818 labelSelector = "label[for='" + this.element.attr("id") + "']"; 6819 this.buttonElement = ancestor.find( labelSelector ); 6820 if ( !this.buttonElement.length ) { 6821 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 6822 this.buttonElement = ancestor.filter( labelSelector ); 6823 if ( !this.buttonElement.length ) { 6824 this.buttonElement = ancestor.find( labelSelector ); 6825 } 6826 } 6827 this.element.addClass( "ui-helper-hidden-accessible" ); 6828 6829 var checked = this.element.is( ":checked" ); 6830 if ( checked ) { 6831 this.buttonElement.addClass( "ui-state-active" ); 6832 } 6833 this.buttonElement.attr( "aria-pressed", checked ); 6834 } else { 6835 this.buttonElement = this.element; 6836 } 6837 }, 6838 6839 widget: function() { 6840 return this.buttonElement; 6841 }, 6842 6843 destroy: function() { 6844 this.element 6845 .removeClass( "ui-helper-hidden-accessible" ); 6846 this.buttonElement 6847 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) 6848 .removeAttr( "role" ) 6849 .removeAttr( "aria-pressed" ) 6850 .html( this.buttonElement.find(".ui-button-text").html() ); 6851 6852 if ( !this.hasTitle ) {
6853 this.buttonElement.removeAttr( "title" ); 6854 } 6855 6856 $.Widget.prototype.destroy.call( this ); 6857 }, 6858 6859 _setOption: function( key, value ) { 6860 $.Widget.prototype._setOption.apply( this, arguments ); 6861 if ( key === "disabled" ) { 6862 if ( value ) { 6863 this.element.propAttr( "disabled", true ); 6864 } else { 6865 this.element.propAttr( "disabled", false ); 6866 } 6867 return; 6868 } 6869 this._resetButton(); 6870 }, 6871 6872 refresh: function() { 6873 var isDisabled = this.element.is( ":disabled" ); 6874 if ( isDisabled !== this.options.disabled ) { 6875 this._setOption( "disabled", isDisabled ); 6876 } 6877 if ( this.type === "radio" ) { 6878 radioGroup( this.element[0] ).each(function() { 6879 if ( $( this ).is( ":checked" ) ) { 6880 $( this ).button( "widget" ) 6881 .addClass( "ui-state-active" ) 6882 .attr( "aria-pressed", "true" ); 6883 } else { 6884 $( this ).button( "widget" ) 6885 .removeClass( "ui-state-active" ) 6886 .attr( "aria-pressed", "false" ); 6887 } 6888 }); 6889 } else if ( this.type === "checkbox" ) { 6890 if ( this.element.is( ":checked" ) ) { 6891 this.buttonElement 6892 .addClass( "ui-state-active" ) 6893 .attr( "aria-pressed", "true" ); 6894 } else { 6895 this.buttonElement 6896 .removeClass( "ui-state-active" ) 6897 .attr( "aria-pressed", "false" ); 6898 } 6899 } 6900 }, 6901 6902 _resetButton: function() { 6903 if ( this.type === "input" ) { 6904 if ( this.options.label ) { 6905 this.element.val( this.options.label ); 6906 } 6907 return; 6908 } 6909 var buttonElement = this.buttonElement.removeClass( typeClasses ), 6910 buttonText = $( "<span></span>", this.element[0].ownerDocument ) 6911 .addClass( "ui-button-text" ) 6912 .html( this.options.label ) 6913 .appendTo( buttonElement.empty() ) 6914 .text(), 6915 icons = this.options.icons, 6916 multipleIcons = icons.primary && icons.secondary, 6917 buttonClasses = []; 6918 6919 if ( icons.primary || icons.secondary ) { 6920 if ( this.options.text ) { 6921 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 6922 } 6923 6924 if ( icons.primary ) { 6925 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 6926 } 6927 6928 if ( icons.secondary ) { 6929 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 6930 } 6931 6932 if ( !this.options.text ) { 6933 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 6934 6935 if ( !this.hasTitle ) { 6936 buttonElement.attr( "title", buttonText ); 6937 } 6938 } 6939 } else { 6940 buttonClasses.push( "ui-button-text-only" ); 6941 } 6942 buttonElement.addClass( buttonClasses.join( " " ) ); 6943 } 6944}); 6945 6946$.widget( "ui.buttonset", { 6947 options: { 6948 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" 6949 }, 6950 6951 _create: function() { 6952 this.element.addClass( "ui-buttonset" ); 6953 }, 6954 6955 _init: function() { 6956 this.refresh(); 6957 }, 6958 6959 _setOption: function( key, value ) { 6960 if ( key === "disabled" ) { 6961 this.buttons.button( "option", key, value ); 6962 } 6963 6964 $.Widget.prototype._setOption.apply( this, arguments ); 6965 }, 6966 6967 refresh: function() { 6968 var rtl = this.element.css( "direction" ) === "rtl"; 6969 6970 this.buttons = this.element.find( this.options.items ) 6971 .filter( ":ui-button" ) 6972 .button( "refresh" ) 6973 .end() 6974 .not( ":ui-button" ) 6975 .button() 6976 .end() 6977 .map(function() { 6978 return $( this ).button( "widget" )[ 0 ]; 6979 }) 6980 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 6981 .filter( ":first" ) 6982 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 6983 .end() 6984 .filter( ":last" ) 6985 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 6986 .end() 6987 .end(); 6988 }, 6989 6990 destroy: function() { 6991 this.element.removeClass( "ui-buttonset" ); 6992 this.buttons 6993 .map(function() { 6994 return $( this ).button( "widget" )[ 0 ]; 6995 }) 6996 .removeClass( "ui-corner-left ui-corner-right" ) 6997 .end() 6998 .button( "destroy" ); 6999 7000 $.Widget.prototype.destroy.call( this ); 7001 } 7002}); 7003 7004}( jQuery ) ); 7005 7006(function( $, undefined ) { 7007 7008$.extend($.ui, { datepicker: { version: "@VERSION" } }); 7009 7010var PROP_NAME = 'datepicker'; 7011var dpuuid = new Date().getTime(); 7012var instActive; 7013 7014/* Date picker manager.
7015 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7016 Settings for (groups of) date pickers are maintained in an instance object, 7017 allowing multiple different settings on the same page. */ 7018 7019function Datepicker() { 7020 this.debug = false; // Change this to true to start debugging 7021 this._curInst = null; // The current instance in use 7022 this._keyEvent = false; // If the last event was a key event 7023 this._disabledInputs = []; // List of date picker inputs that have been disabled 7024 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7025 this._inDialog = false; // True if showing within a "dialog", false if not 7026 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division 7027 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class 7028 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class 7029 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class 7030 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class 7031 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class 7032 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class 7033 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class 7034 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class 7035 this.regional = []; // Available regional settings, indexed by language code 7036 this.regional[''] = { // Default regional settings 7037 closeText: 'Done', // Display text for close link 7038 prevText: 'Prev', // Display text for previous month link 7039 nextText: 'Next', // Display text for next month link 7040 currentText: 'Today', // Display text for current month link 7041 monthNames: ['January','February','March','April','May','June', 7042 'July','August','September','October','November','December'], // Names of months for drop-down and formatting 7043 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting 7044 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting 7045 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting 7046 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday 7047 weekHeader: 'Wk', // Column header for week of the year 7048 dateFormat: 'mm/dd/yy', // See format options on parseDate 7049 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7050 isRTL: false, // True if right-to-left language, false if left-to-right 7051 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7052 yearSuffix: '' // Additional text to append to the year in the month headers 7053 }; 7054 this._defaults = { // Global defaults for all the date picker instances 7055 showOn: 'focus', // 'focus' for popup on focus, 7056 // 'button' for trigger button, or 'both' for either 7057 showAnim: 'fadeIn', // Name of jQuery animation for popup 7058 showOptions: {}, // Options for enhanced animations 7059 defaultDate: null, // Used when field is blank: actual date, 7060 // +/-number for offset from today, null for today 7061 appendText: '', // Display text following the input box, e.g. showing the format 7062 buttonText: '...', // Text for trigger button 7063 buttonImage: '', // URL for trigger button image 7064 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7065 hideIfNoPrevNext: false, // True to hide next/previous month links 7066 // if not applicable, false to just disable them 7067 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7068 gotoCurrent: false, // True if today link goes back to current selection instead 7069 changeMonth: false, // True if month can be selected directly, false if only prev/next 7070 changeYear: false, // True if year can be selected directly, false if only prev/next 7071 yearRange: 'c-10:c+10', // Range of years to display in drop-down, 7072 // either relative to today's year (-nn:+nn), relative to currently displayed year 7073 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7074 showOtherMonths: false, // True to show dates in other months, false to leave blank 7075 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7076 showWeek: false, // True to show week of the year, false to not show it 7077 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7078 // takes a Date and returns the number of the week for it 7079 shortYearCutoff: '+10', // Short year values < this are in the current century, 7080 // > this are in the previous century, 7081 // string value starting with '+' for current year + value 7082 minDate: null, // The earliest selectable date, or null for no limit 7083 maxDate: null, // The latest selectable date, or null for no limit 7084 duration: 'fast', // Duration of display/closure 7085 beforeShowDay: null, // Function that takes a date and returns an array with 7086 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', 7087 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7088 beforeShow: null, // Function that takes an input field and 7089 // returns a set of custom settings for the date picker 7090 onSelect: null, // Define a callback function when a date is selected 7091 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7092 onClose: null, // Define a callback function when the datepicker is closed 7093 numberOfMonths: 1, // Number of months to show at a time 7094 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7095 stepMonths: 1, // Number of months to step back/forward 7096 stepBigMonths: 12, // Number of months to step back/forward for the big links 7097 altField: '', // Selector for an alternate field to store selected dates into 7098 altFormat: '', // The date format to use for the alternate field 7099 constrainInput: true, // The input is constrained by the current date format 7100 showButtonPanel: false, // True to show button panel, false to not show it 7101 autoSize: false, // True to size the input for the date format, false to leave as is 7102 disabled: false // The initial disabled state 7103 }; 7104 $.extend(this._defaults, this.regional['']); 7105 this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')); 7106} 7107 7108$.extend(Datepicker.prototype, { 7109 /* Class name added to elements to indicate already configured with a date picker. */ 7110 markerClassName: 'hasDatepicker', 7111 7112 //Keep track of the maximum number of rows displayed (see #7043) 7113 maxRows: 4, 7114 7115 /* Debug logging (if enabled). */ 7116 log: function () { 7117 if (this.debug) 7118 console.log.apply('', arguments); 7119 }, 7120 7121 // TODO rename to "widget" when switching to widget factory 7122 _widgetDatepicker: function() { 7123 return this.dpDiv; 7124 }, 7125 7126 /* Override the default settings for all instances of the date picker. 7127 @param settings object - the new settings to use as defaults (anonymous object) 7128 @return the manager object */ 7129 setDefaults: function(settings) { 7130 extendRemove(this._defaults, settings || {}); 7131 return this; 7132 }, 7133 7134 /* Attach the date picker to a jQuery selection. 7135 @param target element - the target input field or division or span 7136 @param settings object - the new settings to use for this date picker instance (anonymous) */ 7137 _attachDatepicker: function(target, settings) { 7138 // check for settings on the control itself - in namespace 'date:' 7139 var inlineSettings = null; 7140 for (var attrName in this._defaults) { 7141 var attrValue = target.getAttribute('date:' + attrName); 7142 if (attrValue) { 7143 inlineSettings = inlineSettings || {}; 7144 try { 7145 inlineSettings[attrName] = eval(attrValue); 7146 } catch (err) { 7147 inlineSettings[attrName] = attrValue; 7148 } 7149 } 7150 } 7151 var nodeName = target.nodeName.toLowerCase(); 7152 var inline = (nodeName == 'div' || nodeName == 'span'); 7153 if (!target.id) { 7154 this.uuid += 1; 7155 target.id = 'dp' + this.uuid; 7156 } 7157 var inst = this._newInst($(target), inline); 7158 inst.settings = $.extend({}, settings || {}, inlineSettings || {}); 7159 if (nodeName == 'input') { 7160 this._connectDatepicker(target, inst); 7161 } else if (inline) { 7162 this._inlineDatepicker(target, inst); 7163 } 7164 }, 7165 7166 /* Create a new instance object. */ 7167 _newInst: function(target, inline) { 7168 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars 7169 return {id: id, input: target, // associated target 7170 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7171 drawMonth: 0, drawYear: 0, // month being drawn 7172 inline: inline, // is datepicker inline or not 7173 dpDiv: (!inline ? this.dpDiv : // presentation div 7174 bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))}; 7175 }, 7176 7177 /* Attach the date picker to an input field. */ 7178 _connectDatepicker: function(target, inst) { 7179 var input = $(target); 7180 inst.append = $([]); 7181 inst.trigger = $([]); 7182 if (input.hasClass(this.markerClassName)) 7183 return; 7184 this._attachments(input, inst); 7185 input.addClass(this.markerClassName).keydown(this._doKeyDown). 7186 keypress(this._doKeyPress).keyup(this._doKeyUp). 7187 bind("setData.datepicker", function(event, key, value) { 7188 inst.settings[key] = value; 7189 }).bind("getData.datepicker", function(event, key) { 7190 return this._get(inst, key); 7191 }); 7192 this._autoSize(inst); 7193 $.data(target, PROP_NAME, inst); 7194 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7195 if( inst.settings.disabled ) { 7196 this._disableDatepicker( target ); 7197 } 7198 }, 7199 7200 /* Make attachments based on settings. */ 7201 _attachments: function(input, inst) { 7202 var appendText = this._get(inst, 'appendText'); 7203 var isRTL = this._get(inst, 'isRTL'); 7204 if (inst.append)
7205 inst.append.remove(); 7206 if (appendText) { 7207 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>'); 7208 input[isRTL ? 'before' : 'after'](inst.append); 7209 } 7210 input.unbind('focus', this._showDatepicker); 7211 if (inst.trigger) 7212 inst.trigger.remove(); 7213 var showOn = this._get(inst, 'showOn'); 7214 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field 7215 input.focus(this._showDatepicker); 7216 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked 7217 var buttonText = this._get(inst, 'buttonText'); 7218 var buttonImage = this._get(inst, 'buttonImage'); 7219 inst.trigger = $(this._get(inst, 'buttonImageOnly') ? 7220 $('<img/>').addClass(this._triggerClass). 7221 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 7222 $('<button type="button"></button>').addClass(this._triggerClass). 7223 html(buttonImage == '' ? buttonText : $('<img/>').attr( 7224 { src:buttonImage, alt:buttonText, title:buttonText }))); 7225 input[isRTL ? 'before' : 'after'](inst.trigger); 7226 inst.trigger.click(function() { 7227 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) 7228 $.datepicker._hideDatepicker(); 7229 else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) { 7230 $.datepicker._hideDatepicker(); 7231 $.datepicker._showDatepicker(input[0]); 7232 } else 7233 $.datepicker._showDatepicker(input[0]); 7234 return false; 7235 }); 7236 } 7237 }, 7238 7239 /* Apply the maximum length for the date format. */ 7240 _autoSize: function(inst) { 7241 if (this._get(inst, 'autoSize') && !inst.inline) { 7242 var date = new Date(2009, 12 - 1, 20); // Ensure double digits 7243 var dateFormat = this._get(inst, 'dateFormat'); 7244 if (dateFormat.match(/[DM]/)) { 7245 var findMax = function(names) { 7246 var max = 0; 7247 var maxI = 0; 7248 for (var i = 0; i < names.length; i++) { 7249 if (names[i].length > max) { 7250 max = names[i].length; 7251 maxI = i; 7252 } 7253 } 7254 return maxI; 7255 }; 7256 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 7257 'monthNames' : 'monthNamesShort')))); 7258 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 7259 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); 7260 } 7261 inst.input.attr('size', this._formatDate(inst, date).length); 7262 } 7263 }, 7264 7265 /* Attach an inline date picker to a div. */ 7266 _inlineDatepicker: function(target, inst) { 7267 var divSpan = $(target); 7268 if (divSpan.hasClass(this.markerClassName)) 7269 return; 7270 divSpan.addClass(this.markerClassName).append(inst.dpDiv). 7271 bind("setData.datepicker", function(event, key, value){ 7272 inst.settings[key] = value; 7273 }).bind("getData.datepicker", function(event, key){ 7274 return this._get(inst, key); 7275 }); 7276 $.data(target, PROP_NAME, inst); 7277 this._setDate(inst, this._getDefaultDate(inst), true); 7278 this._updateDatepicker(inst); 7279 this._updateAlternate(inst); 7280 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7281 if( inst.settings.disabled ) { 7282 this._disableDatepicker( target ); 7283 } 7284 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7285 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7286 inst.dpDiv.css( "display", "block" ); 7287 }, 7288 7289 /* Pop-up the date picker in a "dialog" box. 7290 @param input element - ignored 7291 @param date string or Date - the initial date to display 7292 @param onSelect function - the function to call when a date is selected 7293 @param settings object - update the dialog date picker instance's settings (anonymous object) 7294 @param pos int[2] - coordinates for the dialog's position within the screen or 7295 event - with x/y coordinates or 7296 leave empty for default (screen centre) 7297 @return the manager object */ 7298 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 7299 var inst = this._dialogInst; // internal instance 7300 if (!inst) { 7301 this.uuid += 1; 7302 var id = 'dp' + this.uuid; 7303 this._dialogInput = $('<input type="text" id="' + id + 7304 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>'); 7305 this._dialogInput.keydown(this._doKeyDown); 7306 $('body').append(this._dialogInput); 7307 inst = this._dialogInst = this._newInst(this._dialogInput, false); 7308 inst.settings = {}; 7309 $.data(this._dialogInput[0], PROP_NAME, inst); 7310 } 7311 extendRemove(inst.settings, settings || {}); 7312 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); 7313 this._dialogInput.val(date); 7314 7315 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 7316 if (!this._pos) { 7317 var browserWidth = document.documentElement.clientWidth; 7318 var browserHeight = document.documentElement.clientHeight; 7319 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7320 var scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7321 this._pos = // should use actual width/height below 7322 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 7323 } 7324 7325 // move input on screen for focus, but hidden behind dialog 7326 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); 7327 inst.settings.onSelect = onSelect; 7328 this._inDialog = true; 7329 this.dpDiv.addClass(this._dialogClass); 7330 this._showDatepicker(this._dialogInput[0]); 7331 if ($.blockUI) 7332 $.blockUI(this.dpDiv); 7333 $.data(this._dialogInput[0], PROP_NAME, inst); 7334 return this; 7335 }, 7336 7337 /* Detach a datepicker from its control. 7338 @param target element - the target input field or division or span */ 7339 _destroyDatepicker: function(target) { 7340 var $target = $(target); 7341 var inst = $.data(target, PROP_NAME); 7342 if (!$target.hasClass(this.markerClassName)) { 7343 return; 7344 } 7345 var nodeName = target.nodeName.toLowerCase(); 7346 $.removeData(target, PROP_NAME); 7347 if (nodeName == 'input') {
7348 inst.append.remove(); 7349 inst.trigger.remove(); 7350 $target.removeClass(this.markerClassName). 7351 unbind('focus', this._showDatepicker). 7352 unbind('keydown', this._doKeyDown). 7353 unbind('keypress', this._doKeyPress). 7354 unbind('keyup', this._doKeyUp); 7355 } else if (nodeName == 'div' || nodeName == 'span') 7356 $target.removeClass(this.markerClassName).empty(); 7357 }, 7358 7359 /* Enable the date picker to a jQuery selection. 7360 @param target element - the target input field or division or span */ 7361 _enableDatepicker: function(target) { 7362 var $target = $(target); 7363 var inst = $.data(target, PROP_NAME); 7364 if (!$target.hasClass(this.markerClassName)) { 7365 return; 7366 } 7367 var nodeName = target.nodeName.toLowerCase(); 7368 if (nodeName == 'input') { 7369 target.disabled = false; 7370 inst.trigger.filter('button'). 7371 each(function() { this.disabled = false; }).end(). 7372 filter('img').css({opacity: '1.0', cursor: ''}); 7373 } 7374 else if (nodeName == 'div' || nodeName == 'span') { 7375 var inline = $target.children('.' + this._inlineClass); 7376 inline.children().removeClass('ui-state-disabled'); 7377 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7378 removeAttr("disabled"); 7379 } 7380 this._disabledInputs = $.map(this._disabledInputs, 7381 function(value) { return (value == target ? null : value); }); // delete entry 7382 }, 7383 7384 /* Disable the date picker to a jQuery selection. 7385 @param target element - the target input field or division or span */ 7386 _disableDatepicker: function(target) { 7387 var $target = $(target); 7388 var inst = $.data(target, PROP_NAME); 7389 if (!$target.hasClass(this.markerClassName)) { 7390 return; 7391 } 7392 var nodeName = target.nodeName.toLowerCase(); 7393 if (nodeName == 'input') { 7394 target.disabled = true; 7395 inst.trigger.filter('button'). 7396 each(function() { this.disabled = true; }).end(). 7397 filter('img').css({opacity: '0.5', cursor: 'default'}); 7398 } 7399 else if (nodeName == 'div' || nodeName == 'span') { 7400 var inline = $target.children('.' + this._inlineClass); 7401 inline.children().addClass('ui-state-disabled'); 7402 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7403 attr("disabled", "disabled"); 7404 } 7405 this._disabledInputs = $.map(this._disabledInputs, 7406 function(value) { return (value == target ? null : value); }); // delete entry 7407 this._disabledInputs[this._disabledInputs.length] = target; 7408 }, 7409 7410 /* Is the first field in a jQuery collection disabled as a datepicker? 7411 @param target element - the target input field or division or span 7412 @return boolean - true if disabled, false if enabled */ 7413 _isDisabledDatepicker: function(target) { 7414 if (!target) { 7415 return false; 7416 } 7417 for (var i = 0; i < this._disabledInputs.length; i++) { 7418 if (this._disabledInputs[i] == target) 7419 return true; 7420 } 7421 return false; 7422 }, 7423 7424 /* Retrieve the instance data for the target control. 7425 @param target element - the target input field or division or span 7426 @return object - the associated instance data 7427 @throws error if a jQuery problem getting data */ 7428 _getInst: function(target) { 7429 try { 7430 return $.data(target, PROP_NAME); 7431 } 7432 catch (err) { 7433 throw 'Missing instance data for this datepicker'; 7434 } 7435 }, 7436 7437 /* Update or retrieve the settings for a date picker attached to an input field or division. 7438 @param target element - the target input field or division or span 7439 @param name object - the new settings to update or 7440 string - the name of the setting to change or retrieve, 7441 when retrieving also 'all' for all instance settings or 7442 'defaults' for all global defaults 7443 @param value any - the new value for the setting 7444 (omit if above is an object or to retrieve a value) */ 7445 _optionDatepicker: function(target, name, value) { 7446 var inst = this._getInst(target); 7447 if (arguments.length == 2 && typeof name == 'string') { 7448 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : 7449 (inst ? (name == 'all' ? $.extend({}, inst.settings) : 7450 this._get(inst, name)) : null)); 7451 } 7452 var settings = name || {}; 7453 if (typeof name == 'string') { 7454 settings = {}; 7455 settings[name] = value; 7456 } 7457 if (inst) { 7458 if (this._curInst == inst) { 7459 this._hideDatepicker(); 7460 } 7461 var date = this._getDateDatepicker(target, true); 7462 var minDate = this._getMinMaxDate(inst, 'min'); 7463 var maxDate = this._getMinMaxDate(inst, 'max'); 7464 extendRemove(inst.settings, settings); 7465 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7466 if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) 7467 inst.settings.minDate = this._formatDate(inst, minDate); 7468 if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) 7469 inst.settings.maxDate = this._formatDate(inst, maxDate); 7470 this._attachments($(target), inst); 7471 this._autoSize(inst); 7472 this._setDate(inst, date); 7473 this._updateAlternate(inst); 7474 this._updateDatepicker(inst); 7475 } 7476 }, 7477 7478 // change method deprecated 7479 _changeDatepicker: function(target, name, value) { 7480 this._optionDatepicker(target, name, value); 7481 }, 7482 7483 /* Redraw the date picker attached to an input field or division. 7484 @param target element - the target input field or division or span */ 7485 _refreshDatepicker: function(target) { 7486 var inst = this._getInst(target); 7487 if (inst) { 7488 this._updateDatepicker(inst); 7489 } 7490 }, 7491 7492 /* Set the dates for a jQuery selection. 7493 @param target element - the target input field or division or span 7494 @param date Date - the new date */ 7495 _setDateDatepicker: function(target, date) { 7496 var inst = this._getInst(target); 7497 if (inst) { 7498 this._setDate(inst, date); 7499 this._updateDatepicker(inst); 7500 this._updateAlternate(inst); 7501 } 7502 }, 7503 7504 /* Get the date(s) for the first entry in a jQuery selection. 7505 @param target element - the target input field or division or span 7506 @param noDefault boolean - true if no default date is to be used 7507 @return Date - the current date */ 7508 _getDateDatepicker: function(target, noDefault) { 7509 var inst = this._getInst(target); 7510 if (inst && !inst.inline) 7511 this._setDateFromField(inst, noDefault); 7512 return (inst ? this._getDate(inst) : null); 7513 }, 7514 7515 /* Handle keystrokes. */ 7516 _doKeyDown: function(event) { 7517 var inst = $.datepicker._getInst(event.target); 7518 var handled = true; 7519 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); 7520 inst._keyEvent = true; 7521 if ($.datepicker._datepickerShowing) 7522 switch (event.keyCode) { 7523 case 9: $.datepicker._hideDatepicker(); 7524 handled = false; 7525 break; // hide on tab out 7526 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 7527 $.datepicker._currentClass + ')', inst.dpDiv); 7528 if (sel[0]) 7529 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 7530 var onSelect = $.datepicker._get(inst, 'onSelect'); 7531 if (onSelect) { 7532 var dateStr = $.datepicker._formatDate(inst); 7533 7534 // trigger custom callback 7535 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 7536 } 7537 else 7538 $.datepicker._hideDatepicker(); 7539 return false; // don't submit the form 7540 break; // select the value on enter 7541 case 27: $.datepicker._hideDatepicker(); 7542 break; // hide on escape 7543 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7544 -$.datepicker._get(inst, 'stepBigMonths') : 7545 -$.datepicker._get(inst, 'stepMonths')), 'M'); 7546 break; // previous month/year on page up/+ ctrl 7547 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7548 +$.datepicker._get(inst, 'stepBigMonths') : 7549 +$.datepicker._get(inst, 'stepMonths')), 'M'); 7550 break; // next month/year on page down/+ ctrl 7551 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); 7552 handled = event.ctrlKey || event.metaKey; 7553 break; // clear on ctrl or command +end 7554 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); 7555 handled = event.ctrlKey || event.metaKey; 7556 break; // current on ctrl or command +home 7557 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); 7558 handled = event.ctrlKey || event.metaKey; 7559 // -1 day on ctrl or command +left 7560 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7561 -$.datepicker._get(inst, 'stepBigMonths') : 7562 -$.datepicker._get(inst, 'stepMonths')), 'M'); 7563 // next month/year on alt +left on Mac 7564 break; 7565 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); 7566 handled = event.ctrlKey || event.metaKey; 7567 break; // -1 week on ctrl or command +up 7568 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); 7569 handled = event.ctrlKey || event.metaKey; 7570 // +1 day on ctrl or command +right 7571 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7572 +$.datepicker._get(inst, 'stepBigMonths') : 7573 +$.datepicker._get(inst, 'stepMonths')), 'M'); 7574 // next month/year on alt +right 7575 break; 7576 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); 7577 handled = event.ctrlKey || event.metaKey; 7578 break; // +1 week on ctrl or command +down 7579 default: handled = false; 7580 } 7581 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home 7582 $.datepicker._showDatepicker(this); 7583 else { 7584 handled = false; 7585 } 7586 if (handled) { 7587 event.preventDefault(); 7588 event.stopPropagation(); 7589 } 7590 }, 7591 7592 /* Filter entered characters - based on date format. */ 7593 _doKeyPress: function(event) { 7594 var inst = $.datepicker._getInst(event.target); 7595 if ($.datepicker._get(inst, 'constrainInput')) { 7596 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
7597 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); 7598 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); 7599 } 7600 }, 7601 7602 /* Synchronise manual entry and field/alternate field. */ 7603 _doKeyUp: function(event) { 7604 var inst = $.datepicker._getInst(event.target); 7605 if (inst.input.val() != inst.lastVal) { 7606 try { 7607 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), 7608 (inst.input ? inst.input.val() : null), 7609 $.datepicker._getFormatConfig(inst)); 7610 if (date) { // only if valid 7611 $.datepicker._setDateFromField(inst); 7612 $.datepicker._updateAlternate(inst); 7613 $.datepicker._updateDatepicker(inst); 7614 } 7615 } 7616 catch (err) { 7617 $.datepicker.log(err); 7618 } 7619 } 7620 return true; 7621 }, 7622 7623 /* Pop-up the date picker for a given input field. 7624 If false returned from beforeShow event handler do not show. 7625 @param input element - the input field attached to the date picker or 7626 event - if triggered by focus */ 7627 _showDatepicker: function(input) { 7628 input = input.target || input; 7629 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger 7630 input = $('input', input.parentNode)[0]; 7631 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here 7632 return; 7633 var inst = $.datepicker._getInst(input); 7634 if ($.datepicker._curInst && $.datepicker._curInst != inst) { 7635 $.datepicker._curInst.dpDiv.stop(true, true); 7636 if ( inst && $.datepicker._datepickerShowing ) { 7637 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 7638 } 7639 } 7640 var beforeShow = $.datepicker._get(inst, 'beforeShow'); 7641 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 7642 if(beforeShowSettings === false){ 7643 //false 7644 return; 7645 } 7646 extendRemove(inst.settings, beforeShowSettings); 7647 inst.lastVal = null; 7648 $.datepicker._lastInput = input; 7649 $.datepicker._setDateFromField(inst); 7650 if ($.datepicker._inDialog) // hide cursor 7651 input.value = ''; 7652 if (!$.datepicker._pos) { // position below input 7653 $.datepicker._pos = $.datepicker._findPos(input); 7654 $.datepicker._pos[1] += input.offsetHeight; // add the height 7655 } 7656 var isFixed = false; 7657 $(input).parents().each(function() { 7658 isFixed |= $(this).css('position') == 'fixed'; 7659 return !isFixed; 7660 }); 7661 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled 7662 $.datepicker._pos[0] -= document.documentElement.scrollLeft; 7663 $.datepicker._pos[1] -= document.documentElement.scrollTop; 7664 } 7665 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 7666 $.datepicker._pos = null; 7667 //to avoid flashes on Firefox 7668 inst.dpDiv.empty(); 7669 // determine sizing offscreen 7670 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); 7671 $.datepicker._updateDatepicker(inst); 7672 // fix width for dynamic number of date pickers 7673 // and adjust position before showing 7674 offset = $.datepicker._checkOffset(inst, offset, isFixed); 7675 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 7676 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', 7677 left: offset.left + 'px', top: offset.top + 'px'}); 7678 if (!inst.inline) { 7679 var showAnim = $.datepicker._get(inst, 'showAnim'); 7680 var duration = $.datepicker._get(inst, 'duration'); 7681 var postProcess = function() { 7682 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only 7683 if( !! cover.length ){ 7684 var borders = $.datepicker._getBorders(inst.dpDiv); 7685 cover.css({left: -borders[0], top: -borders[1], 7686 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); 7687 } 7688 }; 7689 inst.dpDiv.css('zindex', $(input).css('zindex')+1); 7690 $.datepicker._datepickerShowing = true; 7691 if ($.effects && $.effects[showAnim]) 7692 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); 7693 else 7694 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); 7695 if (!showAnim || !duration) 7696 postProcess(); 7697 if (inst.input.is(':visible') && !inst.input.is(':disabled')) 7698 inst.input.focus(); 7699 $.datepicker._curInst = inst; 7700 } 7701 }, 7702 7703 /* Generate the date picker content. */ 7704 _updateDatepicker: function(inst) { 7705 var self = this; 7706 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7707 var borders = $.datepicker._getBorders(inst.dpDiv); 7708 instActive = inst; // for delegate hover events 7709 inst.dpDiv.empty().append(this._generateHTML(inst));
7710 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only 7711 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 7712 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) 7713 } 7714 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); 7715 var numMonths = this._getNumberOfMonths(inst); 7716 var cols = numMonths[1]; 7717 var width = 17; 7718 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); 7719 if (cols > 1) 7720 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); 7721 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + 7722 'Class']('ui-datepicker-multi'); 7723 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + 7724 'Class']('ui-datepicker-rtl'); 7725 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && 7726 // #6694 - don't focus the input if it's already focused 7727 // this breaks the change event in IE 7728 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) 7729 inst.input.focus(); 7730 // deffered render of the years select (to avoid flashes on Firefox) 7731 if( inst.yearshtml ){ 7732 var origyearshtml = inst.yearshtml; 7733 setTimeout(function(){ 7734 //assure that inst.yearshtml didn't change. 7735 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ 7736 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); 7737 } 7738 origyearshtml = inst.yearshtml = null; 7739 }, 0); 7740 } 7741 }, 7742 7743 /* Retrieve the size of left and top borders for an element. 7744 @param elem (jQuery object) the element of interest 7745 @return (number[2]) the left and top borders */ 7746 _getBorders: function(elem) { 7747 var convert = function(value) { 7748 return {thin: 1, medium: 2, thick: 3}[value] || value; 7749 }; 7750 return [parseFloat(convert(elem.css('border-left-width'))), 7751 parseFloat(convert(elem.css('border-top-width')))]; 7752 }, 7753 7754 /* Check positioning to remain on screen. */ 7755 _checkOffset: function(inst, offset, isFixed) { 7756 var dpWidth = inst.dpDiv.outerWidth(); 7757 var dpHeight = inst.dpDiv.outerHeight(); 7758 var inputWidth = inst.input ? inst.input.outerWidth() : 0; 7759 var inputHeight = inst.input ? inst.input.outerHeight() : 0; 7760 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft(); 7761 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop(); 7762 7763 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); 7764 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; 7765 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 7766 7767 // now check if datepicker is showing outside window viewport - move to a better place if so. 7768 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 7769 Math.abs(offset.left + dpWidth - viewWidth) : 0); 7770 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 7771 Math.abs(dpHeight + inputHeight) : 0); 7772 7773 return offset; 7774 }, 7775 7776 /* Find an object's position on the screen. */ 7777 _findPos: function(obj) { 7778 var inst = this._getInst(obj); 7779 var isRTL = this._get(inst, 'isRTL'); 7780 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { 7781 obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; 7782 } 7783 var position = $(obj).offset(); 7784 return [position.left, position.top]; 7785 }, 7786 7787 /* Hide the date picker from view. 7788 @param input element - the input field attached to the date picker */ 7789 _hideDatepicker: function(input) { 7790 var inst = this._curInst; 7791 if (!inst || (input && inst != $.data(input, PROP_NAME))) 7792 return; 7793 if (this._datepickerShowing) { 7794 var showAnim = this._get(inst, 'showAnim'); 7795 var duration = this._get(inst, 'duration'); 7796 var postProcess = function() { 7797 $.datepicker._tidyDialog(inst); 7798 }; 7799 if ($.effects && $.effects[showAnim]) 7800 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); 7801 else 7802 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : 7803 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); 7804 if (!showAnim) 7805 postProcess(); 7806 this._datepickerShowing = false; 7807 var onClose = this._get(inst, 'onClose'); 7808 if (onClose) 7809 onClose.apply((inst.input ? inst.input[0] : null), 7810 [(inst.input ? inst.input.val() : ''), inst]); 7811 this._lastInput = null; 7812 if (this._inDialog) { 7813 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); 7814 if ($.blockUI) { 7815 $.unblockUI(); 7816 $('body').append(this.dpDiv); 7817 } 7818 } 7819 this._inDialog = false; 7820 } 7821 }, 7822 7823 /* Tidy up after a dialog display. */ 7824 _tidyDialog: function(inst) { 7825 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); 7826 }, 7827 7828 /* Close date picker if clicked elsewhere. */ 7829 _checkExternalClick: function(event) { 7830 if (!$.datepicker._curInst) 7831 return; 7832 7833 var $target = $(event.target), 7834 inst = $.datepicker._getInst($target[0]); 7835 7836 if ( ( ( $target[0].id != $.datepicker._mainDivId && 7837 $target.parents('#' + $.datepicker._mainDivId).length == 0 && 7838 !$target.hasClass($.datepicker.markerClassName) && 7839 !$target.closest("." + $.datepicker._triggerClass).length && 7840 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 7841 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) ) 7842 $.datepicker._hideDatepicker(); 7843 }, 7844 7845 /* Adjust one of the date sub-fields. */ 7846 _adjustDate: function(id, offset, period) { 7847 var target = $(id); 7848 var inst = this._getInst(target[0]); 7849 if (this._isDisabledDatepicker(target[0])) { 7850 return; 7851 } 7852 this._adjustInstDate(inst, offset + 7853 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning 7854 period); 7855 this._updateDatepicker(inst); 7856 }, 7857 7858 /* Action for current link. */ 7859 _gotoToday: function(id) { 7860 var target = $(id); 7861 var inst = this._getInst(target[0]); 7862 if (this._get(inst, 'gotoCurrent') && inst.currentDay) { 7863 inst.selectedDay = inst.currentDay; 7864 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 7865 inst.drawYear = inst.selectedYear = inst.currentYear; 7866 } 7867 else { 7868 var date = new Date(); 7869 inst.selectedDay = date.getDate(); 7870 inst.drawMonth = inst.selectedMonth = date.getMonth(); 7871 inst.drawYear = inst.selectedYear = date.getFullYear(); 7872 } 7873 this._notifyChange(inst); 7874 this._adjustDate(target); 7875 }, 7876 7877 /* Action for selecting a new month/year. */
7878 _selectMonthYear: function(id, select, period) { 7879 var target = $(id); 7880 var inst = this._getInst(target[0]); 7881 inst['selected' + (period == 'M' ? 'Month' : 'Year')] = 7882 inst['draw' + (period == 'M' ? 'Month' : 'Year')] = 7883 parseInt(select.options[select.selectedIndex].value,10); 7884 this._notifyChange(inst); 7885 this._adjustDate(target); 7886 }, 7887 7888 /* Action for selecting a day. */ 7889 _selectDay: function(id, month, year, td) { 7890 var target = $(id); 7891 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 7892 return; 7893 } 7894 var inst = this._getInst(target[0]); 7895 inst.selectedDay = inst.currentDay = $('a', td).html(); 7896 inst.selectedMonth = inst.currentMonth = month; 7897 inst.selectedYear = inst.currentYear = year; 7898 this._selectDate(id, this._formatDate(inst, 7899 inst.currentDay, inst.currentMonth, inst.currentYear)); 7900 }, 7901 7902 /* Erase the input field and hide the date picker. */ 7903 _clearDate: function(id) { 7904 var target = $(id); 7905 var inst = this._getInst(target[0]); 7906 this._selectDate(target, ''); 7907 }, 7908 7909 /* Update the input field with the selected date. */ 7910 _selectDate: function(id, dateStr) { 7911 var target = $(id); 7912 var inst = this._getInst(target[0]); 7913 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 7914 if (inst.input) 7915 inst.input.val(dateStr); 7916 this._updateAlternate(inst); 7917 var onSelect = this._get(inst, 'onSelect'); 7918 if (onSelect) 7919 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 7920 else if (inst.input) 7921 inst.input.trigger('change'); // fire the change event 7922 if (inst.inline) 7923 this._updateDatepicker(inst); 7924 else { 7925 this._hideDatepicker(); 7926 this._lastInput = inst.input[0]; 7927 if (typeof(inst.input[0]) != 'object') 7928 inst.input.focus(); // restore focus 7929 this._lastInput = null; 7930 } 7931 }, 7932 7933 /* Update any alternate field to synchronise with the main field. */ 7934 _updateAlternate: function(inst) { 7935 var altField = this._get(inst, 'altField'); 7936 if (altField) { // update alternate field too 7937 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); 7938 var date = this._getDate(inst); 7939 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 7940 $(altField).each(function() { $(this).val(dateStr); }); 7941 } 7942 }, 7943 7944 /* Set as beforeShowDay function to prevent selection of weekends. 7945 @param date Date - the date to customise 7946 @return [boolean, string] - is this date selectable?, what is its CSS class? */ 7947 noWeekends: function(date) { 7948 var day = date.getDay(); 7949 return [(day > 0 && day < 6), '']; 7950 }, 7951 7952 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 7953 @param date Date - the date to get the week for 7954 @return number - the number of the week within the year that contains this date */ 7955 iso8601Week: function(date) { 7956 var checkDate = new Date(date.getTime()); 7957 // Find Thursday of this week starting on Monday 7958 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 7959 var time = checkDate.getTime(); 7960 checkDate.setMonth(0); // Compare with Jan 1 7961 checkDate.setDate(1); 7962 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 7963 }, 7964 7965 /* Parse a string value into a date object. 7966 See formatDate below for the possible formats. 7967 7968 @param format string - the expected format of the date 7969 @param value string - the date in the above format 7970 @param settings Object - attributes include: 7971 shortYearCutoff number - the cutoff year for determining the century (optional) 7972 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 7973 dayNames string[7] - names of the days from Sunday (optional) 7974 monthNamesShort string[12] - abbreviated names of the months (optional) 7975 monthNames string[12] - names of the months (optional) 7976 @return Date - the extracted date value or null if value is blank */ 7977 parseDate: function (format, value, settings) { 7978 if (format == null || value == null) 7979 throw 'Invalid arguments'; 7980 value = (typeof value == 'object' ? value.toString() : value + ''); 7981 if (value == '') 7982 return null; 7983 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; 7984 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : 7985 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 7986 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; 7987 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; 7988 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; 7989 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; 7990 var year = -1;
7991 var month = -1; 7992 var day = -1; 7993 var doy = -1; 7994 var literal = false; 7995 // Check whether a format character is doubled 7996 var lookAhead = function(match) { 7997 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); 7998 if (matches) 7999 iFormat++; 8000 return matches; 8001 }; 8002 // Extract a number from the string value 8003 var getNumber = function(match) { 8004 var isDoubled = lookAhead(match); 8005 var size = (match == '@' ? 14 : (match == '!' ? 20 : 8006 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); 8007 var digits = new RegExp('^\\d{1,' + size + '}'); 8008 var num = value.substring(iValue).match(digits); 8009 if (!num) 8010 throw 'Missing number at position ' + iValue; 8011 iValue += num[0].length; 8012 return parseInt(num[0], 10); 8013 }; 8014 // Extract a name from the string value and convert to an index 8015 var getName = function(match, shortNames, longNames) { 8016 var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 8017 return [ [k, v] ]; 8018 }).sort(function (a, b) { 8019 return -(a[1].length - b[1].length); 8020 }); 8021 var index = -1; 8022 $.each(names, function (i, pair) { 8023 var name = pair[1]; 8024 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { 8025 index = pair[0]; 8026 iValue += name.length; 8027 return false; 8028 } 8029 }); 8030 if (index != -1) 8031 return index + 1; 8032 else 8033 throw 'Unknown name at position ' + iValue; 8034 }; 8035 // Confirm that a literal character matches the string value 8036 var checkLiteral = function() { 8037 if (value.charAt(iValue) != format.charAt(iFormat)) 8038 throw 'Unexpected literal at position ' + iValue; 8039 iValue++; 8040 }; 8041 var iValue = 0; 8042 for (var iFormat = 0; iFormat < format.length; iFormat++) { 8043 if (literal) 8044 if (format.charAt(iFormat) == "'" && !lookAhead("'")) 8045 literal = false; 8046 else 8047 checkLiteral(); 8048 else 8049 switch (format.charAt(iFormat)) { 8050 case 'd': 8051 day = getNumber('d'); 8052 break; 8053 case 'D': 8054 getName('D', dayNamesShort, dayNames); 8055 break; 8056 case 'o': 8057 doy = getNumber('o'); 8058 break; 8059 case 'm': 8060 month = getNumber('m'); 8061 break; 8062 case 'M': 8063 month = getName('M', monthNamesShort, monthNames); 8064 break; 8065 case 'y': 8066 year = getNumber('y'); 8067 break; 8068 case '@': 8069 var date = new Date(getNumber('@')); 8070 year = date.getFullYear(); 8071 month = date.getMonth() + 1; 8072 day = date.getDate(); 8073 break; 8074 case '!': 8075 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); 8076 year = date.getFullYear(); 8077 month = date.getMonth() + 1; 8078 day = date.getDate(); 8079 break; 8080 case "'": 8081 if (lookAhead("'")) 8082 checkLiteral(); 8083 else 8084 literal = true; 8085 break; 8086 default: 8087 checkLiteral(); 8088 } 8089 } 8090 if (iValue < value.length){ 8091 throw "Extra/unparsed characters found in date: " + value.substring(iValue); 8092 } 8093 if (year == -1) 8094 year = new Date().getFullYear(); 8095 else if (year < 100) 8096 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8097 (year <= shortYearCutoff ? 0 : -100); 8098 if (doy > -1) { 8099 month = 1; 8100 day = doy; 8101 do { 8102 var dim = this._getDaysInMonth(year, month - 1); 8103 if (day <= dim) 8104 break; 8105 month++; 8106 day -= dim; 8107 } while (true); 8108 } 8109 var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 8110 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) 8111 throw 'Invalid date'; // E.g. 31/02/00 8112 return date; 8113 }, 8114 8115 /* Standard date formats. */ 8116 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) 8117 COOKIE: 'D, dd M yy', 8118 ISO_8601: 'yy-mm-dd', 8119 RFC_822: 'D, d M y', 8120 RFC_850: 'DD, dd-M-y', 8121 RFC_1036: 'D, d M y', 8122 RFC_1123: 'D, d M yy', 8123 RFC_2822: 'D, d M yy', 8124 RSS: 'D, d M y', // RFC 822 8125 TICKS: '!', 8126 TIMESTAMP: '@', 8127 W3C: 'yy-mm-dd', // ISO 8601 8128 8129 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 8130 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 8131 8132 /* Format a date object into a string value. 8133 The format can be combinations of the following: 8134 d - day of month (no leading zero) 8135 dd - day of month (two digit) 8136 o - day of year (no leading zeros) 8137 oo - day of year (three digit) 8138 D - day name short 8139 DD - day name long 8140 m - month of year (no leading zero) 8141 mm - month of year (two digit) 8142 M - month name short 8143 MM - month name long 8144 y - year (two digit) 8145 yy - year (four digit) 8146 @ - Unix timestamp (ms since 01/01/1970) 8147 ! - Windows ticks (100ns since 01/01/0001) 8148 '...' - literal text 8149 '' - single quote 8150
8151 @param format string - the desired format of the date 8152 @param date Date - the date value to format 8153 @param settings Object - attributes include: 8154 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8155 dayNames string[7] - names of the days from Sunday (optional) 8156 monthNamesShort string[12] - abbreviated names of the months (optional) 8157 monthNames string[12] - names of the months (optional) 8158 @return string - the date in the above format */ 8159 formatDate: function (format, date, settings) { 8160 if (!date) 8161 return ''; 8162 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; 8163 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; 8164 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; 8165 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; 8166 // Check whether a format character is doubled 8167 var lookAhead = function(match) { 8168 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); 8169 if (matches) 8170 iFormat++; 8171 return matches; 8172 }; 8173 // Format a number, with leading zero if necessary 8174 var formatNumber = function(match, value, len) { 8175 var num = '' + value; 8176 if (lookAhead(match)) 8177 while (num.length < len) 8178 num = '0' + num; 8179 return num; 8180 }; 8181 // Format a name, short or long as requested 8182 var formatName = function(match, value, shortNames, longNames) { 8183 return (lookAhead(match) ? longNames[value] : shortNames[value]); 8184 }; 8185 var output = ''; 8186 var literal = false; 8187 if (date) 8188 for (var iFormat = 0; iFormat < format.length; iFormat++) { 8189 if (literal) 8190 if (format.charAt(iFormat) == "'" && !lookAhead("'")) 8191 literal = false; 8192 else 8193 output += format.charAt(iFormat); 8194 else 8195 switch (format.charAt(iFormat)) { 8196 case 'd': 8197 output += formatNumber('d', date.getDate(), 2); 8198 break; 8199 case 'D': 8200 output += formatName('D', date.getDay(), dayNamesShort, dayNames); 8201 break; 8202 case 'o': 8203 output += formatNumber('o', 8204 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 8205 break; 8206 case 'm': 8207 output += formatNumber('m', date.getMonth() + 1, 2); 8208 break; 8209 case 'M': 8210 output += formatName('M', date.getMonth(), monthNamesShort, monthNames); 8211 break; 8212 case 'y': 8213 output += (lookAhead('y') ? date.getFullYear() : 8214 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); 8215 break; 8216 case '@': 8217 output += date.getTime(); 8218 break; 8219 case '!': 8220 output += date.getTime() * 10000 + this._ticksTo1970; 8221 break; 8222 case "'": 8223 if (lookAhead("'")) 8224 output += "'"; 8225 else 8226 literal = true; 8227 break; 8228 default: 8229 output += format.charAt(iFormat); 8230 } 8231 } 8232 return output; 8233 }, 8234 8235 /* Extract all possible characters from the date format. */ 8236 _possibleChars: function (format) { 8237 var chars = ''; 8238 var literal = false; 8239 // Check whether a format character is doubled 8240 var lookAhead = function(match) { 8241 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); 8242 if (matches) 8243 iFormat++; 8244 return matches; 8245 }; 8246 for (var iFormat = 0; iFormat < format.length; iFormat++) 8247 if (literal) 8248 if (format.charAt(iFormat) == "'" && !lookAhead("'")) 8249 literal = false; 8250 else 8251 chars += format.charAt(iFormat); 8252 else 8253 switch (format.charAt(iFormat)) { 8254 case 'd': case 'm': case 'y': case '@': 8255 chars += '0123456789'; 8256 break; 8257 case 'D': case 'M': 8258 return null; // Accept anything 8259 case "'": 8260 if (lookAhead("'")) 8261 chars += "'"; 8262 else 8263 literal = true; 8264 break; 8265 default: 8266 chars += format.charAt(iFormat); 8267 } 8268 return chars; 8269 }, 8270 8271 /* Get a setting value, defaulting if necessary. */ 8272 _get: function(inst, name) { 8273 return inst.settings[name] !== undefined ? 8274 inst.settings[name] : this._defaults[name]; 8275 }, 8276 8277 /* Parse existing date and initialise date picker. */ 8278 _setDateFromField: function(inst, noDefault) { 8279 if (inst.input.val() == inst.lastVal) { 8280 return; 8281 } 8282 var dateFormat = this._get(inst, 'dateFormat'); 8283 var dates = inst.lastVal = inst.input ? inst.input.val() : null; 8284 var date, defaultDate; 8285 date = defaultDate = this._getDefaultDate(inst); 8286 var settings = this._getFormatConfig(inst); 8287 try { 8288 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 8289 } catch (event) { 8290 this.log(event); 8291 dates = (noDefault ? '' : dates); 8292 } 8293 inst.selectedDay = date.getDate(); 8294 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8295 inst.drawYear = inst.selectedYear = date.getFullYear(); 8296 inst.currentDay = (dates ? date.getDate() : 0); 8297 inst.currentMonth = (dates ? date.getMonth() : 0); 8298 inst.currentYear = (dates ? date.getFullYear() : 0); 8299 this._adjustInstDate(inst); 8300 }, 8301 8302 /* Retrieve the default date shown on opening. */ 8303 _getDefaultDate: function(inst) { 8304 return this._restrictMinMax(inst, 8305 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); 8306 }, 8307 8308 /* A date may be specified as an exact value or a relative one. */ 8309 _determineDate: function(inst, date, defaultDate) { 8310 var offsetNumeric = function(offset) { 8311 var date = new Date(); 8312 date.setDate(date.getDate() + offset); 8313 return date; 8314 }; 8315 var offsetString = function(offset) { 8316 try { 8317 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), 8318 offset, $.datepicker._getFormatConfig(inst)); 8319 } 8320 catch (e) { 8321 // Ignore 8322 } 8323 var date = (offset.toLowerCase().match(/^c/) ? 8324 $.datepicker._getDate(inst) : null) || new Date(); 8325 var year = date.getFullYear();
8326 var month = date.getMonth(); 8327 var day = date.getDate(); 8328 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; 8329 var matches = pattern.exec(offset); 8330 while (matches) { 8331 switch (matches[2] || 'd') { 8332 case 'd' : case 'D' : 8333 day += parseInt(matches[1],10); break; 8334 case 'w' : case 'W' : 8335 day += parseInt(matches[1],10) * 7; break; 8336 case 'm' : case 'M' : 8337 month += parseInt(matches[1],10); 8338 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8339 break; 8340 case 'y': case 'Y' : 8341 year += parseInt(matches[1],10); 8342 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8343 break; 8344 } 8345 matches = pattern.exec(offset); 8346 } 8347 return new Date(year, month, day); 8348 }; 8349 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : 8350 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 8351 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); 8352 if (newDate) { 8353 newDate.setHours(0); 8354 newDate.setMinutes(0); 8355 newDate.setSeconds(0); 8356 newDate.setMilliseconds(0); 8357 } 8358 return this._daylightSavingAdjust(newDate); 8359 }, 8360 8361 /* Handle switch to/from daylight saving. 8362 Hours may be non-zero on daylight saving cut-over: 8363 > 12 when midnight changeover, but then cannot generate 8364 midnight datetime, so jump to 1AM, otherwise reset. 8365 @param date (Date) the date to check 8366 @return (Date) the corrected date */ 8367 _daylightSavingAdjust: function(date) { 8368 if (!date) return null; 8369 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 8370 return date; 8371 }, 8372 8373 /* Set the date(s) directly. */ 8374 _setDate: function(inst, date, noChange) { 8375 var clear = !date; 8376 var origMonth = inst.selectedMonth; 8377 var origYear = inst.selectedYear; 8378 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 8379 inst.selectedDay = inst.currentDay = newDate.getDate(); 8380 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8381 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8382 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) 8383 this._notifyChange(inst); 8384 this._adjustInstDate(inst); 8385 if (inst.input) { 8386 inst.input.val(clear ? '' : this._formatDate(inst)); 8387 } 8388 }, 8389 8390 /* Retrieve the date(s) directly. */ 8391 _getDate: function(inst) { 8392 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : 8393 this._daylightSavingAdjust(new Date( 8394 inst.currentYear, inst.currentMonth, inst.currentDay))); 8395 return startDate; 8396 }, 8397 8398 /* Generate the HTML for the current state of the date picker. */ 8399 _generateHTML: function(inst) { 8400 var today = new Date(); 8401 today = this._daylightSavingAdjust( 8402 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time 8403 var isRTL = this._get(inst, 'isRTL'); 8404 var showButtonPanel = this._get(inst, 'showButtonPanel'); 8405 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); 8406 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); 8407 var numMonths = this._getNumberOfMonths(inst); 8408 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); 8409 var stepMonths = this._get(inst, 'stepMonths'); 8410 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); 8411 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 8412 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 8413 var minDate = this._getMinMaxDate(inst, 'min'); 8414 var maxDate = this._getMinMaxDate(inst, 'max'); 8415 var drawMonth = inst.drawMonth - showCurrentAtPos; 8416 var drawYear = inst.drawYear; 8417 if (drawMonth < 0) { 8418 drawMonth += 12; 8419 drawYear--; 8420 } 8421 if (maxDate) { 8422 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 8423 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 8424 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 8425 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 8426 drawMonth--; 8427 if (drawMonth < 0) { 8428 drawMonth = 11; 8429 drawYear--; 8430 } 8431 } 8432 } 8433 inst.drawMonth = drawMonth; 8434 inst.drawYear = drawYear; 8435 var prevText = this._get(inst, 'prevText'); 8436 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 8437 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 8438 this._getFormatConfig(inst))); 8439 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 8440 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid + 8441 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' + 8442 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' : 8443 (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>')); 8444 var nextText = this._get(inst, 'nextText'); 8445 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 8446 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 8447 this._getFormatConfig(inst))); 8448 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 8449 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid + 8450 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' + 8451 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' : 8452 (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>')); 8453 var currentText = this._get(inst, 'currentText'); 8454 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); 8455 currentText = (!navigationAsDateFormat ? currentText : 8456 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 8457 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid + 8458 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : ''); 8459 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') + 8460 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid + 8461 '.datepicker._gotoToday(\'#' + inst.id + '\');"' + 8462 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : ''; 8463 var firstDay = parseInt(this._get(inst, 'firstDay'),10); 8464 firstDay = (isNaN(firstDay) ? 0 : firstDay); 8465 var showWeek = this._get(inst, 'showWeek'); 8466 var dayNames = this._get(inst, 'dayNames'); 8467 var dayNamesShort = this._get(inst, 'dayNamesShort'); 8468 var dayNamesMin = this._get(inst, 'dayNamesMin'); 8469 var monthNames = this._get(inst, 'monthNames'); 8470 var monthNamesShort = this._get(inst, 'monthNamesShort'); 8471 var beforeShowDay = this._get(inst, 'beforeShowDay'); 8472 var showOtherMonths = this._get(inst, 'showOtherMonths'); 8473 var selectOtherMonths = this._get(inst, 'selectOtherMonths'); 8474 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; 8475 var defaultDate = this._getDefaultDate(inst); 8476 var html = ''; 8477 for (var row = 0; row < numMonths[0]; row++) { 8478 var group = ''; 8479 this.maxRows = 4; 8480 for (var col = 0; col < numMonths[1]; col++) { 8481 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 8482 var cornerClass = ' ui-corner-all'; 8483 var calender = ''; 8484 if (isMultiMonth) { 8485 calender += '<div class="ui-datepicker-group'; 8486 if (numMonths[1] > 1) 8487 switch (col) { 8488 case 0: calender += ' ui-datepicker-group-first'; 8489 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break; 8490 case numMonths[1]-1: calender += ' ui-datepicker-group-last'; 8491 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break; 8492 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break; 8493 } 8494 calender += '">'; 8495 } 8496 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' + 8497 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + 8498 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + 8499 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 8500 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 8501 '</div><table class="ui-datepicker-calendar"><thead>' + 8502 '<tr>'; 8503 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : ''); 8504 for (var dow = 0; dow < 7; dow++) { // days of the week 8505 var day = (dow + firstDay) % 7; 8506 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>
8506' + 8507 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>'; 8508 } 8509 calender += thead + '</tr></thead><tbody>'; 8510 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 8511 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) 8512 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 8513 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 8514 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 8515 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 8516 this.maxRows = numRows; 8517 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 8518 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows 8519 calender += '<tr>'; 8520 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' + 8521 this._get(inst, 'calculateWeek')(printDate) + '</td>'); 8522 for (var dow = 0; dow < 7; dow++) { // create date picker days 8523 var daySettings = (beforeShowDay ? 8524 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); 8525 var otherMonth = (printDate.getMonth() != drawMonth); 8526 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 8527 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 8528 tbody += '<td class="' + 8529 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends 8530 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months 8531 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key 8532 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ? 8533 // or defaultDate is current printedDate and defaultDate is selectedDate 8534 ' ' + this._dayOverClass : '') + // highlight selected day 8535 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days 8536 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates 8537 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day 8538 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different) 8539 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title 8540 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' + 8541 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions 8542 (otherMonth && !showOtherMonths ? ' ' : // display for other months 8543 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' + 8544 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') + 8545 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day 8546 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months 8547 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date 8548 printDate.setDate(printDate.getDate() + 1); 8549 printDate = this._daylightSavingAdjust(printDate); 8550 } 8551 calender += tbody + '</tr>'; 8552 } 8553 drawMonth++; 8554 if (drawMonth > 11) { 8555 drawMonth = 0; 8556 drawYear++; 8557 } 8558 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 8559 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : ''); 8560 group += calender; 8561 } 8562 html += group; 8563 } 8564 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? 8565 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : ''); 8566 inst._keyEvent = false; 8567 return html; 8568 }, 8569 8570 /* Generate the month and year header. */ 8571 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 8572 secondary, monthNames, monthNamesShort) { 8573 var changeMonth = this._get(inst, 'changeMonth'); 8574 var changeYear = this._get(inst, 'changeYear'); 8575 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); 8576 var html = '<div class="ui-datepicker-title">'; 8577 var monthHtml = ''; 8578 // month selection 8579 if (secondary || !changeMonth) 8580 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>'; 8581 else { 8582 var inMinYear = (minDate && minDate.getFullYear() == drawYear); 8583 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); 8584 monthHtml += '<select class="ui-datepicker-month" ' + 8585 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' + 8586 '>';
8587 for (var month = 0; month < 12; month++) { 8588 if ((!inMinYear || month >= minDate.getMonth()) && 8589 (!inMaxYear || month <= maxDate.getMonth())) 8590 monthHtml += '<option value="' + month + '"' + 8591 (month == drawMonth ? ' selected="selected"' : '') + 8592 '>' + monthNamesShort[month] + '</option>'; 8593 } 8594 monthHtml += '</select>'; 8595 } 8596 if (!showMonthAfterYear) 8597 html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); 8598 // year selection 8599 if ( !inst.yearshtml ) { 8600 inst.yearshtml = ''; 8601 if (secondary || !changeYear) 8602 html += '<span class="ui-datepicker-year">' + drawYear + '</span>'; 8603 else { 8604 // determine range of years to display 8605 var years = this._get(inst, 'yearRange').split(':'); 8606 var thisYear = new Date().getFullYear(); 8607 var determineYear = function(value) { 8608 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : 8609 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : 8610 parseInt(value, 10))); 8611 return (isNaN(year) ? thisYear : year); 8612 }; 8613 var year = determineYear(years[0]); 8614 var endYear = Math.max(year, determineYear(years[1] || '')); 8615 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 8616 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 8617 inst.yearshtml += '<select class="ui-datepicker-year" ' + 8618 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' + 8619 '>'; 8620 for (; year <= endYear; year++) { 8621 inst.yearshtml += '<option value="' + year + '"' + 8622 (year == drawYear ? ' selected="selected"' : '') + 8623 '>' + year + '</option>'; 8624 } 8625 inst.yearshtml += '</select>'; 8626 8627 html += inst.yearshtml; 8628 inst.yearshtml = null; 8629 } 8630 } 8631 html += this._get(inst, 'yearSuffix'); 8632 if (showMonthAfterYear) 8633 html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; 8634 html += '</div>'; // Close datepicker_header 8635 return html; 8636 }, 8637 8638 /* Adjust one of the date sub-fields. */ 8639 _adjustInstDate: function(inst, offset, period) { 8640 var year = inst.drawYear + (period == 'Y' ? offset : 0); 8641 var month = inst.drawMonth + (period == 'M' ? offset : 0); 8642 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + 8643 (period == 'D' ? offset : 0); 8644 var date = this._restrictMinMax(inst, 8645 this._daylightSavingAdjust(new Date(year, month, day))); 8646 inst.selectedDay = date.getDate(); 8647 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8648 inst.drawYear = inst.selectedYear = date.getFullYear(); 8649 if (period == 'M' || period == 'Y') 8650 this._notifyChange(inst); 8651 }, 8652 8653 /* Ensure a date is within any min/max bounds. */ 8654 _restrictMinMax: function(inst, date) { 8655 var minDate = this._getMinMaxDate(inst, 'min'); 8656 var maxDate = this._getMinMaxDate(inst, 'max'); 8657 var newDate = (minDate && date < minDate ? minDate : date); 8658 newDate = (maxDate && newDate > maxDate ? maxDate : newDate); 8659 return newDate; 8660 }, 8661 8662 /* Notify change of month/year. */ 8663 _notifyChange: function(inst) { 8664 var onChange = this._get(inst, 'onChangeMonthYear'); 8665 if (onChange) 8666 onChange.apply((inst.input ? inst.input[0] : null), 8667 [inst.selectedYear, inst.selectedMonth + 1, inst]); 8668 }, 8669 8670 /* Determine the number of months to show. */ 8671 _getNumberOfMonths: function(inst) { 8672 var numMonths = this._get(inst, 'numberOfMonths'); 8673 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); 8674 }, 8675 8676 /* Determine the current maximum date - ensure no time components are set. */ 8677 _getMinMaxDate: function(inst, minMax) { 8678 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); 8679 }, 8680 8681 /* Find the number of days in a given month. */ 8682 _getDaysInMonth: function(year, month) { 8683 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 8684 }, 8685 8686 /* Find the day of the week of the first of a month. */ 8687 _getFirstDayOfMonth: function(year, month) { 8688 return new Date(year, month, 1).getDay(); 8689 }, 8690 8691 /* Determines if we should allow a "next/prev" month display change. */ 8692 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 8693 var numMonths = this._getNumberOfMonths(inst); 8694 var date = this._daylightSavingAdjust(new Date(curYear, 8695 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 8696 if (offset < 0) 8697 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 8698 return this._isInRange(inst, date); 8699 }, 8700 8701 /* Is the given date in the accepted range? */ 8702 _isInRange: function(inst, date) { 8703 var minDate = this._getMinMaxDate(inst, 'min'); 8704 var maxDate = this._getMinMaxDate(inst, 'max'); 8705 return ((!minDate || date.getTime() >= minDate.getTime()) && 8706 (!maxDate || date.getTime() <= maxDate.getTime())); 8707 }, 8708 8709 /* Provide the configuration settings for formatting/parsing. */ 8710 _getFormatConfig: function(inst) { 8711 var shortYearCutoff = this._get(inst, 'shortYearCutoff'); 8712 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : 8713 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 8714 return {shortYearCutoff: shortYearCutoff, 8715 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), 8716 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; 8717 }, 8718 8719 /* Format the given date for display. */ 8720 _formatDate: function(inst, day, month, year) { 8721 if (!day) { 8722 inst.currentDay = inst.selectedDay; 8723 inst.currentMonth = inst.selectedMonth; 8724 inst.currentYear = inst.selectedYear; 8725 } 8726 var date = (day ? (typeof day == 'object' ? day : 8727 this._daylightSavingAdjust(new Date(year, month, day))) : 8728 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 8729 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); 8730 } 8731}); 8732 8733/* 8734 * Bind hover events for datepicker elements. 8735 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 8736 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 8737 */ 8738function bindHover(dpDiv) { 8739 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; 8740 return dpDiv.bind('mouseout', function(event) { 8741 var elem = $( event.target ).closest( selector ); 8742 if ( !elem.length ) { 8743 return; 8744 } 8745 elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); 8746 }) 8747 .bind('mouseover', function(event) { 8748 var elem = $( event.target ).closest( selector ); 8749 if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || 8750 !elem.length ) { 8751 return; 8752 } 8753 elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); 8754 elem.addClass('ui-state-hover'); 8755 if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); 8756 if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); 8757 }); 8758} 8759 8760/* jQuery extend now ignores nulls! */ 8761function extendRemove(target, props) { 8762 $.extend(target, props); 8763 for (var name in props) 8764 if (props[name] == null || props[name] == undefined) 8765 target[name] = props[name]; 8766 return target; 8767}; 8768 8769/* Determine whether an object is an array. */ 8770function isArray(a) { 8771 return (a && (($.browser.safari && typeof a == 'object' && a.length) || 8772 (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); 8773}; 8774 8775/* Invoke the datepicker functionality. 8776 @param options string - a command, optionally followed by additional parameters or 8777 Object - settings for attaching new datepicker functionality 8778 @return jQuery object */ 8779$.fn.datepicker = function(options){ 8780 8781 /* Verify an empty collection wasn't passed - Fixes #6976 */ 8782 if ( !this.length ) { 8783 return this; 8784 } 8785 8786 /* Initialise the date picker. */ 8787 if (!$.datepicker.initialized) { 8788 $(document).mousedown($.datepicker._checkExternalClick). 8789 find('body').append($.datepicker.dpDiv); 8790 $.datepicker.initialized = true; 8791 } 8792 8793 var otherArgs = Array.prototype.slice.call(arguments, 1); 8794 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) 8795 return $.datepicker['_' + options + 'Datepicker']. 8796 apply($.datepicker, [this[0]].concat(otherArgs)); 8797 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') 8798 return $.datepicker['_' + options + 'Datepicker']. 8799 apply($.datepicker, [this[0]].concat(otherArgs)); 8800 return this.each(function() { 8801 typeof options == 'string' ? 8802 $.datepicker['_' + options + 'Datepicker']. 8803 apply($.datepicker, [this].concat(otherArgs)) : 8804 $.datepicker._attachDatepicker(this, options); 8805 }); 8806}; 8807 8808$.datepicker = new Datepicker(); // singleton instance 8809$.datepicker.initialized = false; 8810$.datepicker.uuid = new Date().getTime(); 8811$.datepicker.version = "@VERSION"; 8812 8813// Workaround for #4055 8814// Add another global to avoid noConflict issues with inline event handlers 8815window['DP_jQuery_' + dpuuid] = $; 8816 8817})(jQuery); 8818 8819(function( $, undefined ) { 8820 8821var uiDialogClasses = 8822 'ui-dialog ' + 8823 'ui-widget ' + 8824 'ui-widget-content ' + 8825 'ui-corner-all ', 8826 sizeRelatedOptions = { 8827 buttons: true, 8828 height: true, 8829 maxHeight: true, 8830 maxWidth: true, 8831 minHeight: true, 8832 minWidth: true, 8833 width: true 8834 }, 8835 resizableRelatedOptions = { 8836 maxHeight: true, 8837 maxWidth: true, 8838 minHeight: true, 8839 minWidth: true 8840 }, 8841 // support for jQuery 1.3.2 - handle common attrFn methods for dialog 8842 attrFn = $.attrFn || { 8843 val: true, 8844 css: true, 8845 html: true, 8846 text: true, 8847 data: true, 8848 width: true, 8849 height: true, 8850 offset: true, 8851 click: true 8852 }; 8853 8854$.widget("ui.dialog", { 8855 options: { 8856 autoOpen: true, 8857 buttons: {}, 8858 closeOnEscape: true, 8859 closeText: 'close', 8860 dialogClass: '', 8861 draggable: true, 8862 hide: null, 8863 height: 'auto', 8864 maxHeight: false, 8865 maxWidth: false, 8866 minHeight: 150, 8867 minWidth: 150, 8868 modal: false, 8869 position: { 8870 my: 'center', 8871 at: 'center', 8872 collision: 'fit', 8873 // ensure that the titlebar is never outside the document 8874 using: function(pos) { 8875 var topOffset = $(this).css(pos).offset().top; 8876 if (topOffset < 0) { 8877 $(this).css('top', pos.top - topOffset); 8878 } 8879 } 8880 }, 8881 resizable: true, 8882 show: null, 8883 stack: true, 8884 title: '', 8885 width: 300, 8886 zIndex: 1000 8887 }, 8888 8889 _create: function() { 8890 this.originalTitle = this.element.attr('title'); 8891 // #5742 - .attr() might return a DOMElement 8892 if ( typeof this.originalTitle !== "string" ) { 8893 this.originalTitle = ""; 8894 } 8895 8896 this.options.title = this.options.title || this.originalTitle; 8897 var self = this, 8898 options = self.options, 8899 8900 title = options.title || ' ', 8901 titleId = $.ui.dialog.getTitleId(self.element), 8902 8903 uiDialog = (self.uiDialog = $('<div></div>')) 8904 .appendTo(document.body) 8905 .hide() 8906 .addClass(uiDialogClasses + options.dialogClass) 8907 .css({ 8908 zIndex: options.zIndex 8909 }) 8910 // setting tabIndex makes the div focusable 8911 // setting outline to 0 prevents a border on focus in Mozilla 8912 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { 8913 if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 8914 event.keyCode === $.ui.keyCode.ESCAPE) { 8915 8916 self.close(event); 8917 event.preventDefault(); 8918 } 8919 }) 8920 .attr({ 8921 role: 'dialog', 8922 'aria-labelledby': titleId 8923 }) 8924 .mousedown(function(event) { 8925 self.moveToTop(false, event); 8926 }), 8927 8928 uiDialogContent = self.element 8929 .show() 8930 .removeAttr('title') 8931 .addClass( 8932 'ui-dialog-content ' + 8933 'ui-widget-content') 8934 .appendTo(uiDialog), 8935 8936 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>')) 8937 .addClass( 8938 'ui-dialog-titlebar ' + 8939 'ui-widget-header ' + 8940 'ui-corner-all ' + 8941 'ui-helper-clearfix' 8942 ) 8943 .prependTo(uiDialog), 8944 8945 uiDialogTitlebarClose = $('<a href="#"></a>') 8946 .addClass( 8947 'ui-dialog-titlebar-close ' + 8948 'ui-corner-all' 8949 ) 8950 .attr('role', 'button') 8951 .hover( 8952 function() { 8953 uiDialogTitlebarClose.addClass('ui-state-hover'); 8954 }, 8955 function() { 8956 uiDialogTitlebarClose.removeClass('ui-state-hover'); 8957 } 8958 ) 8959 .focus(function() { 8960 uiDialogTitlebarClose.addClass('ui-state-focus'); 8961 }) 8962 .blur(function() { 8963 uiDialogTitlebarClose.removeClass('ui-state-focus'); 8964 }) 8965 .click(function(event) { 8966 self.close(event); 8967 return false; 8968 }) 8969 .appendTo(uiDialogTitlebar), 8970 8971 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>')) 8972 .addClass( 8973 'ui-icon ' + 8974 'ui-icon-closethick' 8975 )
8976 .text(options.closeText) 8977 .appendTo(uiDialogTitlebarClose), 8978 8979 uiDialogTitle = $('<span></span>') 8980 .addClass('ui-dialog-title') 8981 .attr('id', titleId) 8982 .html(title) 8983 .prependTo(uiDialogTitlebar); 8984 8985 //handling of deprecated beforeclose (vs beforeClose) option 8986 //Ticket #4669 http://dev.jqueryui.com/ticket/4669 8987 //TODO: remove in 1.9pre 8988 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { 8989 options.beforeClose = options.beforeclose; 8990 } 8991 8992 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); 8993 8994 if (options.draggable && $.fn.draggable) { 8995 self._makeDraggable(); 8996 } 8997 if (options.resizable && $.fn.resizable) { 8998 self._makeResizable(); 8999 } 9000 9001 self._createButtons(options.buttons); 9002 self._isOpen = false; 9003 9004 if ($.fn.bgiframe) { 9005 uiDialog.bgiframe(); 9006 } 9007 }, 9008 9009 _init: function() { 9010 if ( this.options.autoOpen ) { 9011 this.open(); 9012 } 9013 }, 9014 9015 destroy: function() { 9016 var self = this; 9017 9018 if (self.overlay) { 9019 self.overlay.destroy(); 9020 } 9021 self.uiDialog.hide(); 9022 self.element 9023 .unbind('.dialog') 9024 .removeData('dialog') 9025 .removeClass('ui-dialog-content ui-widget-content') 9026 .hide().appendTo('body'); 9027 self.uiDialog.remove(); 9028 9029 if (self.originalTitle) { 9030 self.element.attr('title', self.originalTitle); 9031 } 9032 9033 return self; 9034 }, 9035 9036 widget: function() { 9037 return this.uiDialog; 9038 }, 9039 9040 close: function(event) { 9041 var self = this, 9042 maxZ, thisZ; 9043 9044 if (false === self._trigger('beforeClose', event)) { 9045 return; 9046 } 9047 9048 if (self.overlay) { 9049 self.overlay.destroy(); 9050 } 9051 self.uiDialog.unbind('keypress.ui-dialog'); 9052 9053 self._isOpen = false; 9054 9055 if (self.options.hide) { 9056 self.uiDialog.hide(self.options.hide, function() { 9057 self._trigger('close', event); 9058 }); 9059 } else { 9060 self.uiDialog.hide(); 9061 self._trigger('close', event); 9062 } 9063 9064 $.ui.dialog.overlay.resize(); 9065 9066 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) 9067 if (self.options.modal) { 9068 maxZ = 0; 9069 $('.ui-dialog').each(function() { 9070 if (this !== self.uiDialog[0]) { 9071 thisZ = $(this).css('z-index'); 9072 if(!isNaN(thisZ)) { 9073 maxZ = Math.max(maxZ, thisZ); 9074 } 9075 } 9076 }); 9077 $.ui.dialog.maxZ = maxZ; 9078 } 9079 9080 return self; 9081 }, 9082 9083 isOpen: function() { 9084 return this._isOpen; 9085 }, 9086 9087 // the force parameter allows us to move modal dialogs to their correct 9088 // position on open 9089 moveToTop: function(force, event) { 9090 var self = this, 9091 options = self.options, 9092 saveScroll; 9093 9094 if ((options.modal && !force) || 9095 (!options.stack && !options.modal)) { 9096 return self._trigger('focus', event); 9097 } 9098 9099 if (options.zIndex > $.ui.dialog.maxZ) { 9100 $.ui.dialog.maxZ = options.zIndex; 9101 } 9102 if (self.overlay) { 9103 $.ui.dialog.maxZ += 1; 9104 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); 9105 } 9106 9107 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. 9108 // http://ui.jquery.com/bugs/ticket/3193 9109 saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; 9110 $.ui.dialog.maxZ += 1; 9111 self.uiDialog.css('z-index', $.ui.dialog.maxZ); 9112 self.element.attr(saveScroll); 9113 self._trigger('focus', event); 9114 9115 return self; 9116 }, 9117 9118 open: function() { 9119 if (this._isOpen) { return; } 9120 9121 var self = this, 9122 options = self.options, 9123 uiDialog = self.uiDialog; 9124 9125 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; 9126 self._size(); 9127 self._position(options.position); 9128 uiDialog.show(options.show); 9129 self.moveToTop(true); 9130 9131 // prevent tabbing out of modal dialogs 9132 if ( options.modal ) { 9133 uiDialog.bind( "keydown.ui-dialog", function( event ) { 9134 if ( event.keyCode !== $.ui.keyCode.TAB ) { 9135 return; 9136 } 9137 9138 var tabbables = $(':tabbable', this), 9139 first = tabbables.filter(':first'), 9140 last = tabbables.filter(':last'); 9141 9142 if (event.target === last[0] && !event.shiftKey) { 9143 first.focus(1); 9144 return false; 9145 } else if (event.target === first[0] && event.shiftKey) { 9146 last.focus(1); 9147 return false; 9148 } 9149 }); 9150 } 9151 9152 // set focus to the first tabbable element in the content area or the first button 9153 // if there are no tabbable elements, set focus on the dialog itself 9154 $(self.element.find(':tabbable').get().concat( 9155 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( 9156 uiDialog.get()))).eq(0).focus(); 9157 9158 self._isOpen = true; 9159 self._trigger('open'); 9160 9161 return self; 9162 }, 9163 9164 _createButtons: function(buttons) { 9165 var self = this, 9166 hasButtons = false,
9167 uiDialogButtonPane = $('<div></div>') 9168 .addClass( 9169 'ui-dialog-buttonpane ' + 9170 'ui-widget-content ' + 9171 'ui-helper-clearfix' 9172 ), 9173 uiButtonSet = $( "<div></div>" ) 9174 .addClass( "ui-dialog-buttonset" ) 9175 .appendTo( uiDialogButtonPane ); 9176 9177 // if we already have a button pane, remove it 9178 self.uiDialog.find('.ui-dialog-buttonpane').remove(); 9179 9180 if (typeof buttons === 'object' && buttons !== null) { 9181 $.each(buttons, function() { 9182 return !(hasButtons = true); 9183 }); 9184 } 9185 if (hasButtons) { 9186 $.each(buttons, function(name, props) { 9187 props = $.isFunction( props ) ? 9188 { click: props, text: name } : 9189 props; 9190 var button = $('<button type="button"></button>') 9191 .click(function() { 9192 props.click.apply(self.element[0], arguments); 9193 }) 9194 .appendTo(uiButtonSet); 9195 // can't use .attr( props, true ) with jQuery 1.3.2. 9196 $.each( props, function( key, value ) { 9197 if ( key === "click" ) { 9198 return; 9199 } 9200 if ( key in attrFn ) { 9201 button[ key ]( value ); 9202 } else { 9203 button.attr( key, value ); 9204 } 9205 }); 9206 if ($.fn.button) { 9207 button.button(); 9208 } 9209 }); 9210 uiDialogButtonPane.appendTo(self.uiDialog); 9211 } 9212 }, 9213 9214 _makeDraggable: function() { 9215 var self = this, 9216 options = self.options, 9217 doc = $(document), 9218 heightBeforeDrag; 9219 9220 function filteredUi(ui) { 9221 return { 9222 position: ui.position, 9223 offset: ui.offset 9224 }; 9225 } 9226 9227 self.uiDialog.draggable({ 9228 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', 9229 handle: '.ui-dialog-titlebar', 9230 containment: 'document', 9231 start: function(event, ui) { 9232 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); 9233 $(this).height($(this).height()).addClass("ui-dialog-dragging"); 9234 self._trigger('dragStart', event, filteredUi(ui)); 9235 }, 9236 drag: function(event, ui) { 9237 self._trigger('drag', event, filteredUi(ui)); 9238 }, 9239 stop: function(event, ui) { 9240 options.position = [ui.position.left - doc.scrollLeft(), 9241 ui.position.top - doc.scrollTop()]; 9242 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); 9243 self._trigger('dragStop', event, filteredUi(ui)); 9244 $.ui.dialog.overlay.resize(); 9245 } 9246 }); 9247 }, 9248 9249 _makeResizable: function(handles) { 9250 handles = (handles === undefined ? this.options.resizable : handles); 9251 var self = this, 9252 options = self.options, 9253 // .ui-resizable has position: relative defined in the stylesheet 9254 // but dialogs have to use absolute or fixed positioning 9255 position = self.uiDialog.css('position'), 9256 resizeHandles = (typeof handles === 'string' ? 9257 handles : 9258 'n,e,s,w,se,sw,ne,nw' 9259 ); 9260 9261 function filteredUi(ui) { 9262 return { 9263 originalPosition: ui.originalPosition, 9264 originalSize: ui.originalSize, 9265 position: ui.position, 9266 size: ui.size 9267 }; 9268 } 9269 9270 self.uiDialog.resizable({ 9271 cancel: '.ui-dialog-content', 9272 containment: 'document', 9273 alsoResize: self.element, 9274 maxWidth: options.maxWidth, 9275 maxHeight: options.maxHeight, 9276 minWidth: options.minWidth, 9277 minHeight: self._minHeight(), 9278 handles: resizeHandles, 9279 start: function(event, ui) { 9280 $(this).addClass("ui-dialog-resizing"); 9281 self._trigger('resizeStart', event, filteredUi(ui)); 9282 }, 9283 resize: function(event, ui) { 9284 self._trigger('resize', event, filteredUi(ui)); 9285 }, 9286 stop: function(event, ui) { 9287 $(this).removeClass("ui-dialog-resizing"); 9288 options.height = $(this).height(); 9289 options.width = $(this).width(); 9290 self._trigger('resizeStop', event, filteredUi(ui)); 9291 $.ui.dialog.overlay.resize(); 9292 } 9293 }) 9294 .css('position', position) 9295 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); 9296 }, 9297 9298 _minHeight: function() { 9299 var options = this.options; 9300 9301 if (options.height === 'auto') { 9302 return options.minHeight; 9303 } else { 9304 return Math.min(options.minHeight, options.height); 9305 } 9306 }, 9307 9308 _position: function(position) { 9309 var myAt = [], 9310 offset = [0, 0], 9311 isVisible; 9312 9313 if (position) { 9314 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( 9315 // if (typeof position == 'string' || $.isArray(position)) { 9316 // myAt = $.isArray(position) ? position : position.split(' '); 9317 9318 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { 9319 myAt = position.split ? position.split(' ') : [position[0], position[1]];
9320 if (myAt.length === 1) { 9321 myAt[1] = myAt[0]; 9322 } 9323 9324 $.each(['left', 'top'], function(i, offsetPosition) { 9325 if (+myAt[i] === myAt[i]) { 9326 offset[i] = myAt[i]; 9327 myAt[i] = offsetPosition; 9328 } 9329 }); 9330 9331 position = { 9332 my: myAt.join(" "), 9333 at: myAt.join(" "), 9334 offset: offset.join(" ") 9335 }; 9336 } 9337 9338 position = $.extend({}, $.ui.dialog.prototype.options.position, position); 9339 } else { 9340 position = $.ui.dialog.prototype.options.position; 9341 } 9342 9343 // need to show the dialog to get the actual offset in the position plugin 9344 isVisible = this.uiDialog.is(':visible'); 9345 if (!isVisible) { 9346 this.uiDialog.show(); 9347 } 9348 this.uiDialog 9349 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 9350 .css({ top: 0, left: 0 }) 9351 .position($.extend({ of: window }, position)); 9352 if (!isVisible) { 9353 this.uiDialog.hide(); 9354 } 9355 }, 9356 9357 _setOptions: function( options ) { 9358 var self = this, 9359 resizableOptions = {}, 9360 resize = false; 9361 9362 $.each( options, function( key, value ) { 9363 self._setOption( key, value ); 9364 9365 if ( key in sizeRelatedOptions ) { 9366 resize = true; 9367 } 9368 if ( key in resizableRelatedOptions ) { 9369 resizableOptions[ key ] = value; 9370 } 9371 }); 9372 9373 if ( resize ) { 9374 this._size(); 9375 } 9376 if ( this.uiDialog.is( ":data(resizable)" ) ) { 9377 this.uiDialog.resizable( "option", resizableOptions ); 9378 } 9379 }, 9380 9381 _setOption: function(key, value){ 9382 var self = this, 9383 uiDialog = self.uiDialog; 9384 9385 switch (key) { 9386 //handling of deprecated beforeclose (vs beforeClose) option 9387 //Ticket #4669 http://dev.jqueryui.com/ticket/4669 9388 //TODO: remove in 1.9pre 9389 case "beforeclose": 9390 key = "beforeClose"; 9391 break; 9392 case "buttons": 9393 self._createButtons(value); 9394 break; 9395 case "closeText": 9396 // ensure that we always pass a string 9397 self.uiDialogTitlebarCloseText.text("" + value); 9398 break; 9399 case "dialogClass": 9400 uiDialog 9401 .removeClass(self.options.dialogClass) 9402 .addClass(uiDialogClasses + value); 9403 break; 9404 case "disabled": 9405 if (value) { 9406 uiDialog.addClass('ui-dialog-disabled'); 9407 } else { 9408 uiDialog.removeClass('ui-dialog-disabled'); 9409 } 9410 break; 9411 case "draggable": 9412 var isDraggable = uiDialog.is( ":data(draggable)" ); 9413 if ( isDraggable && !value ) { 9414 uiDialog.draggable( "destroy" ); 9415 } 9416 9417 if ( !isDraggable && value ) { 9418 self._makeDraggable(); 9419 } 9420 break; 9421 case "position": 9422 self._position(value); 9423 break; 9424 case "resizable": 9425 // currently resizable, becoming non-resizable 9426 var isResizable = uiDialog.is( ":data(resizable)" ); 9427 if (isResizable && !value) { 9428 uiDialog.resizable('destroy'); 9429 } 9430 9431 // currently resizable, changing handles 9432 if (isResizable && typeof value === 'string') { 9433 uiDialog.resizable('option', 'handles', value); 9434 } 9435 9436 // currently non-resizable, becoming resizable 9437 if (!isResizable && value !== false) { 9438 self._makeResizable(value); 9439 } 9440 break; 9441 case "title": 9442 // convert whatever was passed in o a string, for html() to not throw up 9443 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); 9444 break; 9445 } 9446 9447 $.Widget.prototype._setOption.apply(self, arguments); 9448 }, 9449 9450 _size: function() { 9451 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 9452 * divs will both have width and height set, so we need to reset them 9453 */ 9454 var options = this.options, 9455 nonContentHeight, 9456 minContentHeight, 9457 isVisible = this.uiDialog.is( ":visible" ); 9458 9459 // reset content sizing 9460 this.element.show().css({ 9461 width: 'auto', 9462 minHeight: 0, 9463 height: 0 9464 }); 9465 9466 if (options.minWidth > options.width) { 9467 options.width = options.minWidth; 9468 } 9469 9470 // reset wrapper sizing 9471 // determine the height of all the non-content elements 9472 nonContentHeight = this.uiDialog.css({ 9473 height: 'auto', 9474 width: options.width 9475 }) 9476 .height(); 9477 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 9478 9479 if ( options.height === "auto" ) { 9480 // only needed for IE6 support 9481 if ( $.support.minHeight ) { 9482 this.element.css({ 9483 minHeight: minContentHeight, 9484 height: "auto" 9485 }); 9486 } else { 9487 this.uiDialog.show(); 9488 var autoHeight = this.element.css( "height", "auto" ).height(); 9489 if ( !isVisible ) { 9490 this.uiDialog.hide(); 9491 } 9492 this.element.height( Math.max( autoHeight, minContentHeight ) ); 9493 } 9494 } else { 9495 this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); 9496 } 9497 9498 if (this.uiDialog.is(':data(resizable)')) { 9499 this.uiDialog.resizable('option', 'minHeight', this._minHeight()); 9500 } 9501 } 9502}); 9503 9504$.extend($.ui.dialog, { 9505 version: "@VERSION", 9506 9507 uuid: 0, 9508 maxZ: 0, 9509 9510 getTitleId: function($el) { 9511 var id = $el.attr('id'); 9512 if (!id) { 9513 this.uuid += 1; 9514 id = this.uuid; 9515 } 9516 return 'ui-dialog-title-' + id; 9517 }, 9518 9519 overlay: function(dialog) { 9520 this.$el = $.ui.dialog.overlay.create(dialog); 9521 } 9522}); 9523 9524$.extend($.ui.dialog.overlay, { 9525 instances: [], 9526 // reuse old instances due to IE memory leak with alpha transparency (see #5185) 9527 oldInstances: [], 9528 maxZ: 0, 9529 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), 9530 function(event) { return event + '.dialog-overlay'; }).join(' '), 9531 create: function(dialog) { 9532 if (this.instances.length === 0) { 9533 // prevent use of anchors and inputs 9534 // we use a setTimeout in case the overlay is created from an 9535 // event that we're going to be cancelling (see #2804) 9536 setTimeout(function() { 9537 // handle $(el).dialog().dialog('close') (see #4065) 9538 if ($.ui.dialog.overlay.instances.length) { 9539 $(document).bind($.ui.dialog.overlay.events, function(event) { 9540 // stop events if the z-index of the target is < the z-index of the overlay 9541 // we cannot return true when we don't want to cancel the event (#3523) 9542 if ($(event.target).css('zindex') < $.ui.dialog.overlay.maxZ) { 9543 return false; 9544 } 9545 });
9546 } 9547 }, 1); 9548 9549 // allow closing by pressing the escape key 9550 $(document).bind('keydown.dialog-overlay', function(event) { 9551 if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 9552 event.keyCode === $.ui.keyCode.ESCAPE) { 9553 9554 dialog.close(event); 9555 event.preventDefault(); 9556 } 9557 }); 9558 9559 // handle window resize 9560 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); 9561 } 9562 9563 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay')) 9564 .appendTo(document.body) 9565 .css({ 9566 width: this.width(), 9567 height: this.height() 9568 }); 9569 9570 if ($.fn.bgiframe) { 9571 $el.bgiframe(); 9572 } 9573 9574 this.instances.push($el); 9575 return $el; 9576 }, 9577 9578 destroy: function($el) { 9579 var indexOf = $.inArray($el, this.instances); 9580 if (indexOf != -1){ 9581 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); 9582 } 9583 9584 if (this.instances.length === 0) { 9585 $([document, window]).unbind('.dialog-overlay'); 9586 } 9587 9588 $el.remove(); 9589 9590 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) 9591 var maxZ = 0; 9592 $.each(this.instances, function() { 9593 maxZ = Math.max(maxZ, this.css('z-index')); 9594 }); 9595 this.maxZ = maxZ; 9596 }, 9597 9598 height: function() { 9599 var scrollHeight, 9600 offsetHeight; 9601 // handle IE 6 9602 if ($.browser.msie && $.browser.version < 7) { 9603 scrollHeight = Math.max( 9604 document.documentElement.scrollHeight, 9605 document.body.scrollHeight 9606 ); 9607 offsetHeight = Math.max( 9608 document.documentElement.offsetHeight, 9609 document.body.offsetHeight 9610 ); 9611 9612 if (scrollHeight < offsetHeight) { 9613 return $(window).height() + 'px'; 9614 } else { 9615 return scrollHeight + 'px'; 9616 } 9617 // handle "good" browsers 9618 } else { 9619 return $(document).height() + 'px'; 9620 } 9621 }, 9622 9623 width: function() { 9624 var scrollWidth, 9625 offsetWidth; 9626 // handle IE 9627 if ( $.browser.msie ) { 9628 scrollWidth = Math.max( 9629 document.documentElement.scrollWidth, 9630 document.body.scrollWidth 9631 ); 9632 offsetWidth = Math.max( 9633 document.documentElement.offsetWidth, 9634 document.body.offsetWidth 9635 ); 9636 9637 if (scrollWidth < offsetWidth) { 9638 return $(window).width() + 'px'; 9639 } else { 9640 return scrollWidth + 'px'; 9641 } 9642 // handle "good" browsers 9643 } else { 9644 return $(document).width() + 'px'; 9645 } 9646 }, 9647 9648 resize: function() { 9649 /* If the dialog is draggable and the user drags it past the 9650 * right edge of the window, the document becomes wider so we 9651 * need to stretch the overlay. If the user then drags the 9652 * dialog back to the left, the document will become narrower, 9653 * so we need to shrink the overlay to the appropriate size. 9654 * This is handled by shrinking the overlay before setting it 9655 * to the full document size. 9656 */ 9657 var $overlays = $([]); 9658 $.each($.ui.dialog.overlay.instances, function() { 9659 $overlays = $overlays.add(this); 9660 }); 9661 9662 $overlays.css({ 9663 width: 0, 9664 height: 0 9665 }).css({ 9666 width: $.ui.dialog.overlay.width(), 9667 height: $.ui.dialog.overlay.height() 9668 }); 9669 } 9670}); 9671 9672$.extend($.ui.dialog.overlay.prototype, { 9673 destroy: function() { 9674 $.ui.dialog.overlay.destroy(this.$el); 9675 } 9676}); 9677 9678}(jQuery)); 9679 9680(function( $, undefined ) { 9681 9682$.ui = $.ui || {}; 9683 9684var horizontalPositions = /left|center|right/, 9685 verticalPositions = /top|center|bottom/, 9686 center = "center", 9687 support = {}, 9688 _position = $.fn.position, 9689 _offset = $.fn.offset; 9690
9691$.fn.position = function( options ) { 9692 if ( !options || !options.of ) { 9693 return _position.apply( this, arguments ); 9694 } 9695 9696 // make a copy, we don't want to modify arguments 9697 options = $.extend( {}, options ); 9698 9699 var target = $( options.of ), 9700 targetElem = target[0], 9701 collision = ( options.collision || "flip" ).split( " " ), 9702 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], 9703 targetWidth, 9704 targetHeight, 9705 basePosition; 9706 9707 if ( targetElem.nodeType === 9 ) { 9708 targetWidth = target.width(); 9709 targetHeight = target.height(); 9710 basePosition = { top: 0, left: 0 }; 9711 // TODO: use $.isWindow() in 1.9 9712 } else if ( targetElem.setTimeout ) { 9713 targetWidth = target.width(); 9714 targetHeight = target.height(); 9715 basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; 9716 } else if ( targetElem.preventDefault ) { 9717 // force left top to allow flipping 9718 options.at = "left top"; 9719 targetWidth = targetHeight = 0; 9720 basePosition = { top: options.of.pageY, left: options.of.pageX }; 9721 } else { 9722 targetWidth = target.outerWidth(); 9723 targetHeight = target.outerHeight(); 9724 basePosition = target.offset(); 9725 } 9726 9727 // force my and at to have valid horizontal and veritcal positions 9728 // if a value is missing or invalid, it will be converted to center 9729 $.each( [ "my", "at" ], function() { 9730 var pos = ( options[this] || "" ).split( " " ); 9731 if ( pos.length === 1) { 9732 pos = horizontalPositions.test( pos[0] ) ? 9733 pos.concat( [center] ) : 9734 verticalPositions.test( pos[0] ) ? 9735 [ center ].concat( pos ) : 9736 [ center, center ]; 9737 } 9738 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; 9739 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; 9740 options[ this ] = pos; 9741 }); 9742
9743 // normalize collision option 9744 if ( collision.length === 1 ) { 9745 collision[ 1 ] = collision[ 0 ]; 9746 } 9747 9748 // normalize offset option 9749 offset[ 0 ] = parseInt( offset[0], 10 ) || 0; 9750 if ( offset.length === 1 ) { 9751 offset[ 1 ] = offset[ 0 ]; 9752 } 9753 offset[ 1 ] = parseInt( offset[1], 10 ) || 0; 9754 9755 if ( options.at[0] === "right" ) { 9756 basePosition.left += targetWidth; 9757 } else if ( options.at[0] === center ) { 9758 basePosition.left += targetWidth / 2; 9759 } 9760 9761 if ( options.at[1] === "bottom" ) { 9762 basePosition.top += targetHeight; 9763 } else if ( options.at[1] === center ) { 9764 basePosition.top += targetHeight / 2; 9765 } 9766 9767 basePosition.left += offset[ 0 ]; 9768 basePosition.top += offset[ 1 ]; 9769 9770 return this.each(function() { 9771 var elem = $( this ), 9772 elemWidth = elem.outerWidth(), 9773 elemHeight = elem.outerHeight(), 9774 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, 9775 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, 9776 collisionWidth = elemWidth + marginLeft + 9777 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), 9778 collisionHeight = elemHeight + marginTop + 9779 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), 9780 position = $.extend( {}, basePosition ), 9781 collisionPosition; 9782 9783 if ( options.my[0] === "right" ) { 9784 position.left -= elemWidth; 9785 } else if ( options.my[0] === center ) { 9786 position.left -= elemWidth / 2; 9787 } 9788 9789 if ( options.my[1] === "bottom" ) { 9790 position.top -= elemHeight; 9791 } else if ( options.my[1] === center ) { 9792 position.top -= elemHeight / 2; 9793 } 9794 9795 // prevent fractions if jQuery version doesn't support them (see #5280) 9796 if ( !support.fractions ) { 9797 position.left = Math.round( position.left ); 9798 position.top = Math.round( position.top ); 9799 } 9800 9801 collisionPosition = { 9802 left: position.left - marginLeft, 9803 top: position.top - marginTop 9804 }; 9805 9806 $.each( [ "left", "top" ], function( i, dir ) { 9807 if ( $.ui.position[ collision[i] ] ) { 9808 $.ui.position[ collision[i] ][ dir ]( position, { 9809 targetWidth: targetWidth, 9810 targetHeight: targetHeight, 9811 elemWidth: elemWidth, 9812 elemHeight: elemHeight, 9813 collisionPosition: collisionPosition, 9814 collisionWidth: collisionWidth, 9815 collisionHeight: collisionHeight, 9816 offset: offset, 9817 my: options.my, 9818 at: options.at 9819 }); 9820 } 9821 }); 9822 9823 if ( $.fn.bgiframe ) { 9824 elem.bgiframe(); 9825 } 9826 elem.offset( $.extend( position, { using: options.using } ) ); 9827 }); 9828}; 9829 9830$.ui.position = { 9831 fit: { 9832 left: function( position, data ) { 9833 var win = $( window ), 9834 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); 9835 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); 9836 }, 9837 top: function( position, data ) { 9838 var win = $( window ), 9839 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); 9840 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); 9841 } 9842 }, 9843 9844 flip: { 9845 left: function( position, data ) { 9846 if ( data.at[0] === center ) { 9847 return; 9848 } 9849 var win = $( window ), 9850 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), 9851 myOffset = data.my[ 0 ] === "left" ? 9852 -data.elemWidth : 9853 data.my[ 0 ] === "right" ? 9854 data.elemWidth : 9855 0, 9856 atOffset = data.at[ 0 ] === "left" ? 9857 data.targetWidth : 9858 -data.targetWidth, 9859 offset = -2 * data.offset[ 0 ]; 9860 position.left += data.collisionPosition.left < 0 ? 9861 myOffset + atOffset + offset : 9862 over > 0 ? 9863 myOffset + atOffset + offset : 9864 0; 9865 }, 9866 top: function( position, data ) { 9867 if ( data.at[1] === center ) { 9868 return; 9869 } 9870 var win = $( window ), 9871 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), 9872 myOffset = data.my[ 1 ] === "top" ? 9873 -data.elemHeight : 9874 data.my[ 1 ] === "bottom" ? 9875 data.elemHeight : 9876 0, 9877 atOffset = data.at[ 1 ] === "top" ? 9878 data.targetHeight : 9879 -data.targetHeight, 9880 offset = -2 * data.offset[ 1 ]; 9881 position.top += data.collisionPosition.top < 0 ? 9882 myOffset + atOffset + offset : 9883 over > 0 ? 9884 myOffset + atOffset + offset : 9885 0; 9886 } 9887 } 9888}; 9889 9890// offset setter from jQuery 1.4 9891if ( !$.offset.setOffset ) { 9892 $.offset.setOffset = function( elem, options ) { 9893 // set position first, in-case top/left are set even on static elem 9894 if ( /static/.test( $.curCSS( elem, "position" ) ) ) { 9895 elem.style.position = "relative"; 9896 } 9897 var curElem = $( elem ), 9898 curOffset = curElem.offset(), 9899 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, 9900 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, 9901 props = { 9902 top: (options.top - curOffset.top) + curTop, 9903 left: (options.left - curOffset.left) + curLeft 9904 }; 9905 9906 if ( 'using' in options ) { 9907 options.using.call( elem, props ); 9908 } else { 9909 curElem.css( props ); 9910 } 9911 }; 9912 9913 $.fn.offset = function( options ) { 9914 var elem = this[ 0 ]; 9915 if ( !elem || !elem.ownerDocument ) { return null; } 9916 if ( options ) { 9917 return this.each(function() { 9918 $.offset.setOffset( this, options ); 9919 }); 9920 } 9921 return _offset.call( this ); 9922 }; 9923} 9924 9925// fraction support test (older versions of jQuery don't support fractions) 9926(function () { 9927 var body = document.getElementsByTagName( "body" )[ 0 ], 9928 div = document.createElement( "div" ), 9929 testElement, testElementParent, testElementStyle, offset, offsetTotal; 9930 9931 //Create a "fake body" for testing based on method used in jQuery.support 9932 testElement = document.createElement( body ? "div" : "body" ); 9933 testElementStyle = { 9934 visibility: "hidden", 9935 width: 0, 9936 height: 0, 9937 border: 0, 9938 margin: 0, 9939 background: "none" 9940 }; 9941 if ( body ) { 9942 $.extend( testElementStyle, { 9943 position: "absolute",
9944 left: "-1000px", 9945 top: "-1000px" 9946 }); 9947 } 9948 for ( var i in testElementStyle ) { 9949 testElement.style[ i ] = testElementStyle[ i ]; 9950 } 9951 testElement.appendChild( div ); 9952 testElementParent = body || document.documentElement; 9953 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 9954 9955 div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;"; 9956 9957 offset = $( div ).offset( function( _, offset ) { 9958 return offset; 9959 }).offset(); 9960 9961 testElement.innerHTML = ""; 9962 testElementParent.removeChild( testElement ); 9963 9964 offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 ); 9965 support.fractions = offsetTotal > 21 && offsetTotal < 22; 9966})(); 9967 9968}( jQuery )); 9969 9970(function( $, undefined ) { 9971 9972$.widget( "ui.progressbar", { 9973 options: { 9974 value: 0, 9975 max: 100 9976 }, 9977 9978 min: 0, 9979 9980 _create: function() { 9981 this.element 9982 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 9983 .attr({ 9984 role: "progressbar", 9985 "aria-valuemin": this.min, 9986 "aria-valuemax": this.options.max, 9987 "aria-valuenow": this._value() 9988 }); 9989 9990 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 9991 .appendTo( this.element ); 9992 9993 this.oldValue = this._value(); 9994 this._refreshValue(); 9995 }, 9996 9997 destroy: function() { 9998 this.element 9999 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10000 .removeAttr( "role" ) 10001 .removeAttr( "aria-valuemin" ) 10002 .removeAttr( "aria-valuemax" ) 10003 .removeAttr( "aria-valuenow" ); 10004 10005 this.valueDiv.remove(); 10006 10007 $.Widget.prototype.destroy.apply( this, arguments ); 10008 }, 10009 10010 value: function( newValue ) { 10011 if ( newValue === undefined ) { 10012 return this._value(); 10013 } 10014 10015 this._setOption( "value", newValue ); 10016 return this; 10017 }, 10018 10019 _setOption: function( key, value ) { 10020 if ( key === "value" ) { 10021 this.options.value = value; 10022 this._refreshValue(); 10023 if ( this._value() === this.options.max ) { 10024 this._trigger( "complete" ); 10025 } 10026 } 10027 10028 $.Widget.prototype._setOption.apply( this, arguments ); 10029 }, 10030 10031 _value: function() { 10032 var val = this.options.value; 10033 // normalize invalid value 10034 if ( typeof val !== "number" ) { 10035 val = 0; 10036 } 10037 return Math.min( this.options.max, Math.max( this.min, val ) ); 10038 }, 10039 10040 _percentage: function() { 10041 return 100 * this._value() / this.options.max; 10042 }, 10043 10044 _refreshValue: function() { 10045 var value = this.value(); 10046 var percentage = this._percentage(); 10047 10048 if ( this.oldValue !== value ) { 10049 this.oldValue = value; 10050 this._trigger( "change" ); 10051 } 10052 10053 this.valueDiv 10054 .toggle( value > this.min ) 10055 .toggleClass( "ui-corner-right", value === this.options.max ) 10056 .width( percentage.toFixed(0) + "%" ); 10057 this.element.attr( "aria-valuenow", value ); 10058 } 10059}); 10060 10061$.extend( $.ui.progressbar, { 10062 version: "@VERSION" 10063}); 10064 10065})( jQuery ); 10066 10067(function( $, undefined ) { 10068 10069// number of pages in a slider 10070// (how many times can you page up/down to go through the whole range) 10071var numPages = 5; 10072 10073$.widget( "ui.slider", $.ui.mouse, { 10074 10075 widgetEventPrefix: "slide", 10076 10077 options: { 10078 animate: false, 10079 distance: 0, 10080 max: 100, 10081 min: 0, 10082 orientation: "horizontal", 10083 range: false, 10084 step: 1, 10085 value: 0, 10086 values: null 10087 }, 10088 10089 _create: function() { 10090 var self = this, 10091 o = this.options, 10092 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 10093 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 10094 handleCount = ( o.values && o.values.length ) || 1, 10095 handles = []; 10096 10097 this._keySliding = false; 10098 this._mouseSliding = false; 10099 this._animateOff = true; 10100 this._handleIndex = null; 10101 this._detectOrientation(); 10102 this._mouseInit(); 10103 10104 this.element 10105 .addClass( "ui-slider" + 10106 " ui-slider-" + this.orientation + 10107 " ui-widget" + 10108 " ui-widget-content" + 10109 " ui-corner-all" + 10110 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); 10111 10112 this.range = $([]); 10113 10114 if ( o.range ) { 10115 if ( o.range === true ) { 10116 if ( !o.values ) { 10117 o.values = [ this._valueMin(), this._valueMin() ]; 10118 } 10119 if ( o.values.length && o.values.length !== 2 ) { 10120 o.values = [ o.values[0], o.values[0] ]; 10121 } 10122 } 10123 10124 this.range = $( "<div></div>" ) 10125 .appendTo( this.element ) 10126 .addClass( "ui-slider-range" + 10127 // note: this isn't the most fittingly semantic framework class for this element, 10128 // but worked best visually with a variety of themes 10129 " ui-widget-header" + 10130 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); 10131 } 10132 10133 for ( var i = existingHandles.length; i < handleCount; i += 1 ) { 10134 handles.push( handle ); 10135 } 10136 10137 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); 10138 10139 this.handle = this.handles.eq( 0 ); 10140 10141 this.handles.add( this.range ).filter( "a" ) 10142 .click(function( event ) { 10143 event.preventDefault(); 10144 }) 10145 .hover(function() { 10146 if ( !o.disabled ) { 10147 $( this ).addClass( "ui-state-hover" ); 10148 } 10149 }, function() { 10150 $( this ).removeClass( "ui-state-hover" ); 10151 }) 10152 .focus(function() { 10153 if ( !o.disabled ) { 10154 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); 10155 $( this ).addClass( "ui-state-focus" ); 10156 } else { 10157 $( this ).blur(); 10158 } 10159 }) 10160 .blur(function() { 10161 $( this ).removeClass( "ui-state-focus" ); 10162 }); 10163 10164 this.handles.each(function( i ) { 10165 $( this ).data( "index.ui-slider-handle", i ); 10166 }); 10167 10168 this.handles 10169 .keydown(function( event ) { 10170 var index = $( this ).data( "index.ui-slider-handle" ), 10171 allowed, 10172 curVal, 10173 newVal, 10174 step; 10175 10176 if ( self.options.disabled ) { 10177 return; 10178 } 10179 10180 switch ( event.keyCode ) { 10181 case $.ui.keyCode.HOME: 10182 case $.ui.keyCode.END: 10183 case $.ui.keyCode.PAGE_UP: 10184 case $.ui.keyCode.PAGE_DOWN: 10185 case $.ui.keyCode.UP: 10186 case $.ui.keyCode.RIGHT: 10187 case $.ui.keyCode.DOWN: 10188 case $.ui.keyCode.LEFT: 10189 event.preventDefault(); 10190 if ( !self._keySliding ) { 10191 self._keySliding = true; 10192 $( this ).addClass( "ui-state-active" ); 10193 allowed = self._start( event, index ); 10194 if ( allowed === false ) { 10195 return; 10196 } 10197 } 10198 break; 10199 } 10200 10201 step = self.options.step; 10202 if ( self.options.values && self.options.values.length ) { 10203 curVal = newVal = self.values( index ); 10204 } else { 10205 curVal = newVal = self.value(); 10206 } 10207 10208 switch ( event.keyCode ) { 10209 case $.ui.keyCode.HOME: 10210 newVal = self._valueMin(); 10211 break; 10212 case $.ui.keyCode.END: 10213 newVal = self._valueMax(); 10214 break; 10215 case $.ui.keyCode.PAGE_UP: 10216 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); 10217 break; 10218 case $.ui.keyCode.PAGE_DOWN: 10219 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); 10220 break; 10221 case $.ui.keyCode.UP: 10222 case $.ui.keyCode.RIGHT: 10223 if ( curVal === self._valueMax() ) { 10224 return; 10225 } 10226 newVal = self._trimAlignValue( curVal + step ); 10227 break; 10228 case $.ui.keyCode.DOWN: 10229 case $.ui.keyCode.LEFT: 10230 if ( curVal === self._valueMin() ) { 10231 return; 10232 } 10233 newVal = self._trimAlignValue( curVal - step ); 10234 break; 10235 } 10236 10237 self._slide( event, index, newVal ); 10238 }) 10239 .keyup(function( event ) { 10240 var index = $( this ).data( "index.ui-slider-handle" ); 10241 10242 if ( self._keySliding ) { 10243 self._keySliding = false; 10244 self._stop( event, index ); 10245 self._change( event, index ); 10246 $( this ).removeClass( "ui-state-active" ); 10247 } 10248 10249 }); 10250 10251 this._refreshValue(); 10252 10253 this._animateOff = false; 10254 }, 10255 10256 destroy: function() { 10257 this.handles.remove(); 10258 this.range.remove(); 10259 10260 this.element 10261 .removeClass( "ui-slider" + 10262 " ui-slider-horizontal" + 10263 " ui-slider-vertical" + 10264 " ui-slider-disabled" + 10265 " ui-widget" + 10266 " ui-widget-content" + 10267 " ui-corner-all" ) 10268 .removeData( "slider" ) 10269 .unbind( ".slider" ); 10270 10271 this._mouseDestroy(); 10272 10273 return this; 10274 }, 10275 10276 _mouseCapture: function( event ) { 10277 var o = this.options, 10278 position, 10279 normValue, 10280 distance, 10281 closestHandle, 10282 self, 10283 index, 10284 allowed, 10285 offset, 10286 mouseOverHandle; 10287 10288 if ( o.disabled ) { 10289 return false; 10290 } 10291 10292 this.elementSize = { 10293 width: this.element.outerWidth(), 10294 height: this.element.outerHeight() 10295 }; 10296 this.elementOffset = this.element.offset(); 10297 10298 position = { x: event.pageX, y: event.pageY }; 10299 normValue = this._normValueFromMouse( position ); 10300 distance = this._valueMax() - this._valueMin() + 1; 10301 self = this; 10302 this.handles.each(function( i ) { 10303 var thisDistance = Math.abs( normValue - self.values(i) ); 10304 if ( distance > thisDistance ) { 10305 distance = thisDistance; 10306 closestHandle = $( this ); 10307 index = i; 10308 } 10309 }); 10310 10311 // workaround for bug #3736 (if both handles of a range are at 0, 10312 // the first is always used as the one with least distance, 10313 // and moving it is obviously prevented by preventing negative ranges) 10314 if( o.range === true && this.values(1) === o.min ) { 10315 index += 1;
10316 closestHandle = $( this.handles[index] ); 10317 } 10318 10319 allowed = this._start( event, index ); 10320 if ( allowed === false ) { 10321 return false; 10322 } 10323 this._mouseSliding = true; 10324 10325 self._handleIndex = index; 10326 10327 closestHandle 10328 .addClass( "ui-state-active" ) 10329 .focus(); 10330 10331 offset = closestHandle.offset(); 10332 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); 10333 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 10334 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 10335 top: event.pageY - offset.top - 10336 ( closestHandle.height() / 2 ) - 10337 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 10338 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 10339 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 10340 }; 10341 10342 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 10343 this._slide( event, index, normValue ); 10344 } 10345 this._animateOff = true; 10346 return true; 10347 }, 10348 10349 _mouseStart: function( event ) { 10350 return true; 10351 }, 10352 10353 _mouseDrag: function( event ) { 10354 var position = { x: event.pageX, y: event.pageY }, 10355 normValue = this._normValueFromMouse( position ); 10356 10357 this._slide( event, this._handleIndex, normValue ); 10358 10359 return false; 10360 }, 10361 10362 _mouseStop: function( event ) { 10363 this.handles.removeClass( "ui-state-active" ); 10364 this._mouseSliding = false; 10365 10366 this._stop( event, this._handleIndex ); 10367 this._change( event, this._handleIndex ); 10368 10369 this._handleIndex = null; 10370 this._clickOffset = null; 10371 this._animateOff = false; 10372 10373 return false; 10374 }, 10375 10376 _detectOrientation: function() { 10377 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 10378 }, 10379 10380 _normValueFromMouse: function( position ) { 10381 var pixelTotal, 10382 pixelMouse, 10383 percentMouse, 10384 valueTotal, 10385 valueMouse; 10386 10387 if ( this.orientation === "horizontal" ) { 10388 pixelTotal = this.elementSize.width; 10389 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 10390 } else { 10391 pixelTotal = this.elementSize.height; 10392 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 10393 } 10394 10395 percentMouse = ( pixelMouse / pixelTotal ); 10396 if ( percentMouse > 1 ) { 10397 percentMouse = 1; 10398 } 10399 if ( percentMouse < 0 ) { 10400 percentMouse = 0; 10401 } 10402 if ( this.orientation === "vertical" ) { 10403 percentMouse = 1 - percentMouse; 10404 } 10405 10406 valueTotal = this._valueMax() - this._valueMin(); 10407 valueMouse = this._valueMin() + percentMouse * valueTotal; 10408 10409 return this._trimAlignValue( valueMouse ); 10410 }, 10411 10412 _start: function( event, index ) { 10413 var uiHash = { 10414 handle: this.handles[ index ], 10415 value: this.value() 10416 }; 10417 if ( this.options.values && this.options.values.length ) { 10418 uiHash.value = this.values( index ); 10419 uiHash.values = this.values(); 10420 } 10421 return this._trigger( "start", event, uiHash ); 10422 }, 10423 10424 _slide: function( event, index, newVal ) { 10425 var otherVal, 10426 newValues, 10427 allowed; 10428 10429 if ( this.options.values && this.options.values.length ) { 10430 otherVal = this.values( index ? 0 : 1 ); 10431 10432 if ( ( this.options.values.length === 2 && this.options.range === true ) && 10433 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 10434 ) { 10435 newVal = otherVal; 10436 } 10437 10438 if ( newVal !== this.values( index ) ) { 10439 newValues = this.values(); 10440 newValues[ index ] = newVal; 10441 // A slide can be canceled by returning false from the slide callback 10442 allowed = this._trigger( "slide", event, { 10443 handle: this.handles[ index ], 10444 value: newVal, 10445 values: newValues 10446 } ); 10447 otherVal = this.values( index ? 0 : 1 ); 10448 if ( allowed !== false ) { 10449 this.values( index, newVal, true ); 10450 } 10451 } 10452 } else { 10453 if ( newVal !== this.value() ) { 10454 // A slide can be canceled by returning false from the slide callback 10455 allowed = this._trigger( "slide", event, { 10456 handle: this.handles[ index ], 10457 value: newVal 10458 } ); 10459 if ( allowed !== false ) { 10460 this.value( newVal ); 10461 } 10462 } 10463 } 10464 }, 10465 10466 _stop: function( event, index ) { 10467 var uiHash = { 10468 handle: this.handles[ index ], 10469 value: this.value() 10470 }; 10471 if ( this.options.values && this.options.values.length ) { 10472 uiHash.value = this.values( index ); 10473 uiHash.values = this.values();
vendor: 5,764 bytes, lines 10474-10680
10474 } 10475 10476 this._trigger( "stop", event, uiHash ); 10477 }, 10478 10479 _change: function( event, index ) { 10480 if ( !this._keySliding && !this._mouseSliding ) { 10481 var uiHash = { 10482 handle: this.handles[ index ], 10483 value: this.value() 10484 }; 10485 if ( this.options.values && this.options.values.length ) { 10486 uiHash.value = this.values( index ); 10487 uiHash.values = this.values(); 10488 } 10489 10490 this._trigger( "change", event, uiHash ); 10491 } 10492 }, 10493 10494 value: function( newValue ) { 10495 if ( arguments.length ) { 10496 this.options.value = this._trimAlignValue( newValue ); 10497 this._refreshValue(); 10498 this._change( null, 0 ); 10499 return; 10500 } 10501 10502 return this._value(); 10503 }, 10504 10505 values: function( index, newValue ) { 10506 var vals, 10507 newValues, 10508 i; 10509 10510 if ( arguments.length > 1 ) { 10511 this.options.values[ index ] = this._trimAlignValue( newValue ); 10512 this._refreshValue(); 10513 this._change( null, index ); 10514 return; 10515 } 10516 10517 if ( arguments.length ) { 10518 if ( $.isArray( arguments[ 0 ] ) ) { 10519 vals = this.options.values; 10520 newValues = arguments[ 0 ]; 10521 for ( i = 0; i < vals.length; i += 1 ) { 10522 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 10523 this._change( null, i ); 10524 } 10525 this._refreshValue(); 10526 } else { 10527 if ( this.options.values && this.options.values.length ) { 10528 return this._values( index ); 10529 } else { 10530 return this.value(); 10531 } 10532 } 10533 } else { 10534 return this._values(); 10535 } 10536 }, 10537 10538 _setOption: function( key, value ) { 10539 var i, 10540 valsLength = 0; 10541 10542 if ( $.isArray( this.options.values ) ) { 10543 valsLength = this.options.values.length; 10544 } 10545 10546 $.Widget.prototype._setOption.apply( this, arguments ); 10547 10548 switch ( key ) { 10549 case "disabled": 10550 if ( value ) { 10551 this.handles.filter( ".ui-state-focus" ).blur(); 10552 this.handles.removeClass( "ui-state-hover" ); 10553 this.handles.propAttr( "disabled", true ); 10554 this.element.addClass( "ui-disabled" ); 10555 } else { 10556 this.handles.propAttr( "disabled", false ); 10557 this.element.removeClass( "ui-disabled" ); 10558 } 10559 break; 10560 case "orientation": 10561 this._detectOrientation(); 10562 this.element 10563 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 10564 .addClass( "ui-slider-" + this.orientation ); 10565 this._refreshValue(); 10566 break; 10567 case "value": 10568 this._animateOff = true; 10569 this._refreshValue(); 10570 this._change( null, 0 ); 10571 this._animateOff = false; 10572 break; 10573 case "values": 10574 this._animateOff = true; 10575 this._refreshValue(); 10576 for ( i = 0; i < valsLength; i += 1 ) { 10577 this._change( null, i ); 10578 } 10579 this._animateOff = false; 10580 break; 10581 } 10582 }, 10583 10584 //internal value getter 10585 // _value() returns value trimmed by min and max, aligned by step 10586 _value: function() { 10587 var val = this.options.value; 10588 val = this._trimAlignValue( val ); 10589 10590 return val; 10591 }, 10592 10593 //internal values getter 10594 // _values() returns array of values trimmed by min and max, aligned by step 10595 // _values( index ) returns single value trimmed by min and max, aligned by step 10596 _values: function( index ) { 10597 var val, 10598 vals, 10599 i; 10600 10601 if ( arguments.length ) { 10602 val = this.options.values[ index ]; 10603 val = this._trimAlignValue( val ); 10604 10605 return val; 10606 } else { 10607 // .slice() creates a copy of the array 10608 // this copy gets trimmed by min and max and then returned 10609 vals = this.options.values.slice(); 10610 for ( i = 0; i < vals.length; i+= 1) { 10611 vals[ i ] = this._trimAlignValue( vals[ i ] ); 10612 } 10613 10614 return vals; 10615 } 10616 }, 10617 10618 // returns the step-aligned value that val is closest to, between (inclusive) min and max 10619 _trimAlignValue: function( val ) { 10620 if ( val <= this._valueMin() ) { 10621 return this._valueMin(); 10622 } 10623 if ( val >= this._valueMax() ) { 10624 return this._valueMax(); 10625 } 10626 var step = ( this.options.step > 0 ) ? this.options.step : 1, 10627 valModStep = (val - this._valueMin()) % step, 10628 alignValue = val - valModStep; 10629 10630 if ( Math.abs(valModStep) * 2 >= step ) { 10631 alignValue += ( valModStep > 0 ) ? step : ( -step ); 10632 } 10633 10634 // Since JavaScript has problems with large floats, round 10635 // the final value to 5 digits after the decimal point (see #4124) 10636 return parseFloat( alignValue.toFixed(5) ); 10637 }, 10638 10639 _valueMin: function() { 10640 return this.options.min; 10641 }, 10642 10643 _valueMax: function() { 10644 return this.options.max; 10645 }, 10646 10647 _refreshValue: function() { 10648 var oRange = this.options.range, 10649 o = this.options, 10650 self = this, 10651 animate = ( !this._animateOff ) ? o.animate : false, 10652 valPercent, 10653 _set = {}, 10654 lastValPercent, 10655 value, 10656 valueMin, 10657 valueMax; 10658 10659 if ( this.options.values && this.options.values.length ) { 10660 this.handles.each(function( i, j ) { 10661 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; 10662 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10663 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10664 if ( self.options.range === true ) { 10665 if ( self.orientation === "horizontal" ) { 10666 if ( i === 0 ) { 10667 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 10668 } 10669 if ( i === 1 ) { 10670 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10671 } 10672 } else { 10673 if ( i === 0 ) { 10674 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 10675 } 10676 if ( i === 1 ) { 10677 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10678 } 10679 } 10680 }
10681 lastValPercent = valPercent; 10682 }); 10683 } else { 10684 value = this.value(); 10685 valueMin = this._valueMin(); 10686 valueMax = this._valueMax(); 10687 valPercent = ( valueMax !== valueMin ) ? 10688 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 10689 0; 10690 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10691 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10692 10693 if ( oRange === "min" && this.orientation === "horizontal" ) { 10694 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 10695 } 10696 if ( oRange === "max" && this.orientation === "horizontal" ) { 10697 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10698 } 10699 if ( oRange === "min" && this.orientation === "vertical" ) { 10700 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 10701 } 10702 if ( oRange === "max" && this.orientation === "vertical" ) { 10703 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10704 } 10705 } 10706 } 10707 10708}); 10709 10710$.extend( $.ui.slider, { 10711 version: "@VERSION" 10712}); 10713 10714}(jQuery)); 10715 10716(function( $, undefined ) { 10717 10718var tabId = 0, 10719 listId = 0; 10720 10721function getNextTabId() { 10722 return ++tabId; 10723} 10724 10725function getNextListId() { 10726 return ++listId; 10727} 10728 10729$.widget( "ui.tabs", { 10730 options: { 10731 add: null, 10732 ajaxOptions: null, 10733 cache: false, 10734 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } 10735 collapsible: false, 10736 disable: null, 10737 disabled: [], 10738 enable: null, 10739 event: "click", 10740 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } 10741 idPrefix: "ui-tabs-", 10742 load: null, 10743 panelTemplate: "<div></div>", 10744 remove: null, 10745 select: null, 10746 show: null, 10747 spinner: "<em>Loading…</em>", 10748 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>" 10749 }, 10750 10751 _create: function() { 10752 this._tabify( true ); 10753 }, 10754 10755 _setOption: function( key, value ) { 10756 if ( key == "selected" ) { 10757 if (this.options.collapsible && value == this.options.selected ) { 10758 return; 10759 } 10760 this.select( value ); 10761 } else { 10762 this.options[ key ] = value; 10763 this._tabify(); 10764 } 10765 }, 10766 10767 _tabId: function( a ) { 10768 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || 10769 this.options.idPrefix + getNextTabId(); 10770 }, 10771 10772 _sanitizeSelector: function( hash ) { 10773 // we need this because an id may contain a ":" 10774 return hash.replace( /:/g, "\\:" ); 10775 }, 10776 10777 _cookie: function() { 10778 var cookie = this.cookie || 10779 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); 10780 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); 10781 }, 10782 10783 _ui: function( tab, panel ) { 10784 return { 10785 tab: tab, 10786 panel: panel, 10787 index: this.anchors.index( tab ) 10788 }; 10789 }, 10790 10791 _cleanup: function() { 10792 // restore all former loading tabs labels 10793 this.lis.filter( ".ui-state-processing" ) 10794 .removeClass( "ui-state-processing" ) 10795 .find( "span:data(label.tabs)" ) 10796 .each(function() { 10797 var el = $( this ); 10798 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); 10799 }); 10800 }, 10801 10802 _tabify: function( init ) { 10803 var self = this, 10804 o = this.options, 10805 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash 10806 10807 this.list = this.element.find( "ol,ul" ).eq( 0 ); 10808 this.lis = $( " > li:has(a[href])", this.list ); 10809 this.anchors = this.lis.map(function() { 10810 return $( "a", this )[ 0 ]; 10811 }); 10812 this.panels = $( [] ); 10813 10814 this.anchors.each(function( i, a ) { 10815 var href = $( a ).attr( "href" ); 10816 // For dynamically created HTML that contains a hash as href IE < 8 expands 10817 // such href to the full page url with hash and then misinterprets tab as ajax. 10818 // Same consideration applies for an added tab with a fragment identifier 10819 // since a[href=#fragment-identifier] does unexpectedly not match. 10820 // Thus normalize href attribute... 10821 var hrefBase = href.split( "#" )[ 0 ], 10822 baseEl; 10823 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || 10824 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { 10825 href = a.hash; 10826 a.href = href; 10827 } 10828 10829 // inline tab 10830 if ( fragmentId.test( href ) ) { 10831 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); 10832 // remote tab 10833 // prevent loading the page itself if href is just "#" 10834 } else if ( href && href !== "#" ) {
10835 // required for restore on destroy 10836 $.data( a, "href.tabs", href ); 10837 10838 // TODO until #3808 is fixed strip fragment identifier from url 10839 // (IE fails to load from such url) 10840 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); 10841 10842 var id = self._tabId( a ); 10843 a.href = "#" + id; 10844 var $panel = self.element.find( "#" + id ); 10845 if ( !$panel.length ) { 10846 $panel = $( o.panelTemplate ) 10847 .attr( "id", id ) 10848 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 10849 .insertAfter( self.panels[ i - 1 ] || self.list ); 10850 $panel.data( "destroy.tabs", true ); 10851 } 10852 self.panels = self.panels.add( $panel ); 10853 // invalid tab href 10854 } else { 10855 o.disabled.push( i ); 10856 } 10857 }); 10858 10859 // initialization from scratch 10860 if ( init ) { 10861 // attach necessary classes for styling 10862 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); 10863 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); 10864 this.lis.addClass( "ui-state-default ui-corner-top" ); 10865 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); 10866 10867 // Selected tab 10868 // use "selected" option or try to retrieve: 10869 // 1. from fragment identifier in url 10870 // 2. from cookie 10871 // 3. from selected class attribute on <li> 10872 if ( o.selected === undefined ) { 10873 if ( location.hash ) { 10874 this.anchors.each(function( i, a ) { 10875 if ( a.hash == location.hash ) { 10876 o.selected = i; 10877 return false; 10878 } 10879 }); 10880 } 10881 if ( typeof o.selected !== "number" && o.cookie ) { 10882 o.selected = parseInt( self._cookie(), 10 ); 10883 } 10884 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { 10885 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); 10886 } 10887 o.selected = o.selected || ( this.lis.length ? 0 : -1 ); 10888 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release 10889 o.selected = -1; 10890 } 10891 10892 // sanity check - default to first tab... 10893 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) 10894 ? o.selected 10895 : 0; 10896 10897 // Take disabling tabs via class attribute from HTML 10898 // into account and update option properly. 10899 // A selected tab cannot become disabled. 10900 o.disabled = $.unique( o.disabled.concat( 10901 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { 10902 return self.lis.index( n ); 10903 }) 10904 ) ).sort(); 10905 10906 if ( $.inArray( o.selected, o.disabled ) != -1 ) { 10907 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 ); 10908 } 10909 10910 // highlight selected tab 10911 this.panels.addClass( "ui-tabs-hide" ); 10912 this.lis.removeClass( "ui-tabs-selected ui-state-active" ); 10913 // check for length avoids error when initializing empty list 10914 if ( o.selected >= 0 && this.anchors.length ) { 10915 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); 10916 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); 10917 10918 // seems to be expected behavior that the show callback is fired 10919 self.element.queue( "tabs", function() { 10920 self._trigger( "show", null, 10921 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); 10922 }); 10923 10924 this.load( o.selected ); 10925 } 10926 10927 // clean up to avoid memory leaks in certain versions of IE 6 10928 // TODO: namespace this event 10929 $( window ).bind( "unload", function() { 10930 self.lis.add( self.anchors ).unbind( ".tabs" ); 10931 self.lis = self.anchors = self.panels = null; 10932 }); 10933 // update selected after add/remove 10934 } else { 10935 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); 10936 } 10937 10938 // update collapsible 10939 // TODO: use .toggleClass() 10940 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); 10941 10942 // set or update cookie after init and add/remove respectively 10943 if ( o.cookie ) { 10944 this._cookie( o.selected, o.cookie ); 10945 } 10946 10947 // disable tabs 10948 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { 10949 $( li )[ $.inArray( i, o.disabled ) != -1 && 10950 // TODO: use .toggleClass() 10951 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); 10952 } 10953 10954 // reset cache if switching from cached to not cached 10955 if ( o.cache === false ) { 10956 this.anchors.removeData( "cache.tabs" ); 10957 } 10958 10959 // remove all handlers before, tabify may run on existing tabs after add or option change 10960 this.lis.add( this.anchors ).unbind( ".tabs" ); 10961 10962 if ( o.event !== "mouseover" ) { 10963 var addState = function( state, el ) { 10964 if ( el.is( ":not(.ui-state-disabled)" ) ) { 10965 el.addClass( "ui-state-" + state ); 10966 } 10967 }; 10968 var removeState = function( state, el ) { 10969 el.removeClass( "ui-state-" + state ); 10970 }; 10971 this.lis.bind( "mouseover.tabs" , function() { 10972 addState( "hover", $( this ) ); 10973 }); 10974 this.lis.bind( "mouseout.tabs", function() { 10975 removeState( "hover", $( this ) ); 10976 }); 10977 this.anchors.bind( "focus.tabs", function() { 10978 addState( "focus", $( this ).closest( "li" ) ); 10979 }); 10980 this.anchors.bind( "blur.tabs", function() { 10981 removeState( "focus", $( this ).closest( "li" ) ); 10982 }); 10983 } 10984 10985 // set up animations 10986 var hideFx, showFx; 10987 if ( o.fx ) { 10988 if ( $.isArray( o.fx ) ) { 10989 hideFx = o.fx[ 0 ]; 10990 showFx = o.fx[ 1 ]; 10991 } else { 10992 hideFx = showFx = o.fx; 10993 } 10994 } 10995 10996 // Reset certain styles left over from animation 10997 // and prevent IE's ClearType bug... 10998 function resetStyle( $el, fx ) { 10999 $el.css( "display", "" ); 11000 if ( !$.support.opacity && fx.opacity ) { 11001 $el[ 0 ].style.removeAttribute( "filter" ); 11002 } 11003 } 11004 11005 // Show a tab... 11006 var showTab = showFx 11007 ? function( clicked, $show ) { 11008 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); 11009 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way 11010 .animate( showFx, showFx.duration || "normal", function() { 11011 resetStyle( $show, showFx ); 11012 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); 11013 });
11014 } 11015 : function( clicked, $show ) { 11016 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); 11017 $show.removeClass( "ui-tabs-hide" ); 11018 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); 11019 }; 11020 11021 // Hide a tab, $show is optional... 11022 var hideTab = hideFx 11023 ? function( clicked, $hide ) { 11024 $hide.animate( hideFx, hideFx.duration || "normal", function() { 11025 self.lis.removeClass( "ui-tabs-selected ui-state-active" ); 11026 $hide.addClass( "ui-tabs-hide" ); 11027 resetStyle( $hide, hideFx ); 11028 self.element.dequeue( "tabs" ); 11029 }); 11030 } 11031 : function( clicked, $hide, $show ) { 11032 self.lis.removeClass( "ui-tabs-selected ui-state-active" ); 11033 $hide.addClass( "ui-tabs-hide" ); 11034 self.element.dequeue( "tabs" ); 11035 }; 11036 11037 // attach tab event handler, unbind to avoid duplicates from former tabifying... 11038 this.anchors.bind( o.event + ".tabs", function() { 11039 var el = this, 11040 $li = $(el).closest( "li" ), 11041 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), 11042 $show = self.element.find( self._sanitizeSelector( el.hash ) ); 11043 11044 // If tab is already selected and not collapsible or tab disabled or 11045 // or is already loading or click callback returns false stop here. 11046 // Check if click handler returns false last so that it is not executed 11047 // for a disabled or loading tab! 11048 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || 11049 $li.hasClass( "ui-state-disabled" ) || 11050 $li.hasClass( "ui-state-processing" ) || 11051 self.panels.filter( ":animated" ).length || 11052 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { 11053 this.blur(); 11054 return false; 11055 } 11056 11057 o.selected = self.anchors.index( this ); 11058 11059 self.abort(); 11060 11061 // if tab may be closed 11062 if ( o.collapsible ) { 11063 if ( $li.hasClass( "ui-tabs-selected" ) ) { 11064 o.selected = -1; 11065 11066 if ( o.cookie ) { 11067 self._cookie( o.selected, o.cookie ); 11068 } 11069 11070 self.element.queue( "tabs", function() { 11071 hideTab( el, $hide ); 11072 }).dequeue( "tabs" ); 11073 11074 this.blur(); 11075 return false; 11076 } else if ( !$hide.length ) { 11077 if ( o.cookie ) { 11078 self._cookie( o.selected, o.cookie ); 11079 } 11080 11081 self.element.queue( "tabs", function() { 11082 showTab( el, $show ); 11083 }); 11084 11085 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 11086 self.load( self.anchors.index( this ) ); 11087 11088 this.blur(); 11089 return false; 11090 } 11091 } 11092 11093 if ( o.cookie ) { 11094 self._cookie( o.selected, o.cookie ); 11095 } 11096 11097 // show new tab 11098 if ( $show.length ) { 11099 if ( $hide.length ) { 11100 self.element.queue( "tabs", function() { 11101 hideTab( el, $hide ); 11102 }); 11103 } 11104 self.element.queue( "tabs", function() { 11105 showTab( el, $show ); 11106 }); 11107 11108 self.load( self.anchors.index( this ) ); 11109 } else { 11110 throw "jQuery UI Tabs: Mismatching fragment identifier."; 11111 } 11112 11113 // Prevent IE from keeping other link focussed when using the back button 11114 // and remove dotted border from clicked link. This is controlled via CSS 11115 // in modern browsers; blur() removes focus from address bar in Firefox 11116 // which can become a usability and annoying problem with tabs('rotate'). 11117 if ( $.browser.msie ) { 11118 this.blur(); 11119 } 11120 }); 11121 11122 // disable click in any case 11123 this.anchors.bind( "click.tabs", function(){ 11124 return false; 11125 }); 11126 }, 11127 11128 _getIndex: function( index ) { 11129 // meta-function to give users option to provide a href string instead of a numerical index. 11130 // also sanitizes numerical indexes to valid values. 11131 if ( typeof index == "string" ) { 11132 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 11133 } 11134 11135 return index; 11136 }, 11137 11138 destroy: function() { 11139 var o = this.options; 11140 11141 this.abort(); 11142 11143 this.element 11144 .unbind( ".tabs" ) 11145 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ) 11146 .removeData( "tabs" ); 11147 11148 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); 11149 11150 this.anchors.each(function() { 11151 var href = $.data( this, "href.tabs" ); 11152 if ( href ) { 11153 this.href = href; 11154 } 11155 var $this = $( this ).unbind( ".tabs" );
11156 $.each( [ "href", "load", "cache" ], function( i, prefix ) { 11157 $this.removeData( prefix + ".tabs" ); 11158 }); 11159 }); 11160 11161 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() { 11162 if ( $.data( this, "destroy.tabs" ) ) { 11163 $( this ).remove(); 11164 } else { 11165 $( this ).removeClass([ 11166 "ui-state-default", 11167 "ui-corner-top", 11168 "ui-tabs-selected", 11169 "ui-state-active", 11170 "ui-state-hover", 11171 "ui-state-focus", 11172 "ui-state-disabled", 11173 "ui-tabs-panel", 11174 "ui-widget-content", 11175 "ui-corner-bottom", 11176 "ui-tabs-hide" 11177 ].join( " " ) ); 11178 } 11179 }); 11180 11181 if ( o.cookie ) { 11182 this._cookie( null, o.cookie ); 11183 } 11184 11185 return this; 11186 }, 11187 11188 add: function( url, label, index ) { 11189 if ( index === undefined ) { 11190 index = this.anchors.length; 11191 } 11192 11193 var self = this, 11194 o = this.options, 11195 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), 11196 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); 11197 11198 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); 11199 11200 // try to find an existing element before creating a new one 11201 var $panel = self.element.find( "#" + id ); 11202 if ( !$panel.length ) { 11203 $panel = $( o.panelTemplate ) 11204 .attr( "id", id ) 11205 .data( "destroy.tabs", true ); 11206 } 11207 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); 11208 11209 if ( index >= this.lis.length ) { 11210 $li.appendTo( this.list ); 11211 $panel.appendTo( this.list[ 0 ].parentNode ); 11212 } else { 11213 $li.insertBefore( this.lis[ index ] ); 11214 $panel.insertBefore( this.panels[ index ] ); 11215 } 11216 11217 o.disabled = $.map( o.disabled, function( n, i ) { 11218 return n >= index ? ++n : n; 11219 }); 11220 11221 this._tabify(); 11222 11223 if ( this.anchors.length == 1 ) { 11224 o.selected = 0; 11225 $li.addClass( "ui-tabs-selected ui-state-active" ); 11226 $panel.removeClass( "ui-tabs-hide" ); 11227 this.element.queue( "tabs", function() { 11228 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); 11229 }); 11230 11231 this.load( 0 ); 11232 } 11233 11234 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); 11235 return this; 11236 }, 11237 11238 remove: function( index ) { 11239 index = this._getIndex( index ); 11240 var o = this.options, 11241 $li = this.lis.eq( index ).remove(), 11242 $panel = this.panels.eq( index ).remove(); 11243 11244 // If selected tab was removed focus tab to the right or 11245 // in case the last tab was removed the tab to the left. 11246 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { 11247 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); 11248 } 11249 11250 o.disabled = $.map( 11251 $.grep( o.disabled, function(n, i) { 11252 return n != index; 11253 }), 11254 function( n, i ) { 11255 return n >= index ? --n : n; 11256 }); 11257 11258 this._tabify(); 11259 11260 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); 11261 return this; 11262 }, 11263 11264 enable: function( index ) { 11265 index = this._getIndex( index ); 11266 var o = this.options; 11267 if ( $.inArray( index, o.disabled ) == -1 ) { 11268 return; 11269 } 11270 11271 this.lis.eq( index ).removeClass( "ui-state-disabled" ); 11272 o.disabled = $.grep( o.disabled, function( n, i ) { 11273 return n != index; 11274 }); 11275 11276 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); 11277 return this; 11278 }, 11279 11280 disable: function( index ) { 11281 index = this._getIndex( index ); 11282 var self = this, o = this.options; 11283 // cannot disable already selected tab 11284 if ( index != o.selected ) { 11285 this.lis.eq( index ).addClass( "ui-state-disabled" ); 11286 11287 o.disabled.push( index ); 11288 o.disabled.sort(); 11289 11290 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); 11291 } 11292 11293 return this; 11294 }, 11295 11296 select: function( index ) { 11297 index = this._getIndex( index ); 11298 if ( index == -1 ) { 11299 if ( this.options.collapsible && this.options.selected != -1 ) { 11300 index = this.options.selected; 11301 } else { 11302 return this; 11303 } 11304 } 11305 this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); 11306 return this; 11307 }, 11308 11309 load: function( index ) { 11310 index = this._getIndex( index ); 11311 var self = this, 11312 o = this.options, 11313 a = this.anchors.eq( index )[ 0 ], 11314 url = $.data( a, "load.tabs" ); 11315 11316 this.abort(); 11317 11318 // not remote or from cache 11319 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { 11320 this.element.dequeue( "tabs" ); 11321 return; 11322 } 11323 11324 // load remote from here on 11325 this.lis.eq( index ).addClass( "ui-state-processing" ); 11326 11327 if ( o.spinner ) { 11328 var span = $( "span", a ); 11329 span.data( "label.tabs", span.html() ).html( o.spinner ); 11330 } 11331 11332 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { 11333 url: url, 11334 success: function( r, s ) { 11335 self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); 11336 11337 // take care of tab labels 11338 self._cleanup(); 11339 11340 if ( o.cache ) { 11341 $.data( a, "cache.tabs", true ); 11342 } 11343 11344 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); 11345 try {
11346 o.ajaxOptions.success( r, s ); 11347 } 11348 catch ( e ) {} 11349 }, 11350 error: function( xhr, s, e ) { 11351 // take care of tab labels 11352 self._cleanup(); 11353 11354 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); 11355 try { 11356 // Passing index avoid a race condition when this method is 11357 // called after the user has selected another tab. 11358 // Pass the anchor that initiated this request allows 11359 // loadError to manipulate the tab content panel via $(a.hash) 11360 o.ajaxOptions.error( xhr, s, index, a ); 11361 } 11362 catch ( e ) {} 11363 } 11364 } ) ); 11365 11366 // last, so that load event is fired before show... 11367 self.element.dequeue( "tabs" ); 11368 11369 return this; 11370 }, 11371 11372 abort: function() { 11373 // stop possibly running animations 11374 this.element.queue( [] ); 11375 this.panels.stop( false, true ); 11376 11377 // "tabs" queue must not contain more than two elements, 11378 // which are the callbacks for the latest clicked tab... 11379 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); 11380 11381 // terminate pending requests from other tabs 11382 if ( this.xhr ) { 11383 this.xhr.abort(); 11384 delete this.xhr; 11385 } 11386 11387 // take care of tab labels 11388 this._cleanup(); 11389 return this; 11390 }, 11391 11392 url: function( index, url ) { 11393 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); 11394 return this; 11395 }, 11396 11397 length: function() { 11398 return this.anchors.length; 11399 } 11400}); 11401 11402$.extend( $.ui.tabs, { 11403 version: "@VERSION" 11404}); 11405 11406/* 11407 * Tabs Extensions 11408 */ 11409 11410/* 11411 * Rotate 11412 */ 11413$.extend( $.ui.tabs.prototype, { 11414 rotation: null, 11415 rotate: function( ms, continuing ) { 11416 var self = this, 11417 o = this.options; 11418 11419 var rotate = self._rotate || ( self._rotate = function( e ) { 11420 clearTimeout( self.rotation ); 11421 self.rotation = setTimeout(function() { 11422 var t = o.selected; 11423 self.select( ++t < self.anchors.length ? t : 0 ); 11424 }, ms ); 11425 11426 if ( e ) { 11427 e.stopPropagation(); 11428 } 11429 }); 11430 11431 var stop = self._unrotate || ( self._unrotate = !continuing 11432 ? function(e) { 11433 if (e.clientX) { // in case of a true click 11434 self.rotate(null); 11435 } 11436 } 11437 : function( e ) { 11438 rotate(); 11439 }); 11440 11441 // start rotation 11442 if ( ms ) { 11443 this.element.bind( "tabsshow", rotate ); 11444 this.anchors.bind( o.event + ".tabs", stop ); 11445 rotate(); 11446 // stop rotation 11447 } else { 11448 clearTimeout( self.rotation ); 11449 this.element.unbind( "tabsshow", rotate ); 11450 this.anchors.unbind( o.event + ".tabs", stop ); 11451 delete this._rotate; 11452 delete this._unrotate; 11453 } 11454 11455 return this; 11456 } 11457}); 11458 11459})( 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.