| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /*! 2 * jQuery UI Draggable 1.14.2 3 * https://jqueryui.com 4 * 5 * Copyright OpenJS Foundation and other contributors 6 * Released under the MIT license. 7 * https://jquery.org/license 8 */ 9 10 //>>label: Draggable 11 //>>group: Interactions 12 //>>description: Enables dragging functionality for any element. 13 //>>docs: https://api.jqueryui.com/draggable/ 14 //>>demos: https://jqueryui.com/draggable/ 15 //>>css.structure: ../../themes/base/draggable.css 16 17 ( function( factory ) { 18 "use strict"; 19 20 if ( typeof define === "function" && define.amd ) { 21 22 // AMD. Register as an anonymous module. 23 define( [ 24 "jquery", 25 "./mouse", 26 "../data", 27 "../plugin", 28 "../scroll-parent", 29 "../version", 30 "../widget" 31 ], factory ); 32 } else { 33 34 // Browser globals 35 factory( jQuery ); 36 } 37 } )( function( $ ) { 38 "use strict"; 39 40 $.widget( "ui.draggable", $.ui.mouse, { 41 version: "1.14.2", 42 widgetEventPrefix: "drag", 43 options: { 44 addClasses: true, 45 appendTo: "parent", 46 axis: false, 47 connectToSortable: false, 48 containment: false, 49 cursor: "auto", 50 cursorAt: false, 51 grid: false, 52 handle: false, 53 helper: "original", 54 iframeFix: false, 55 opacity: false, 56 refreshPositions: false, 57 revert: false, 58 revertDuration: 500, 59 scope: "default", 60 scroll: true, 61 scrollSensitivity: 20, 62 scrollSpeed: 20, 63 snap: false, 64 snapMode: "both", 65 snapTolerance: 20, 66 stack: false, 67 zIndex: false, 68 69 // Callbacks 70 drag: null, 71 start: null, 72 stop: null 73 }, 74 _create: function() { 75 76 if ( this.options.helper === "original" ) { 77 this._setPositionRelative(); 78 } 79 if ( this.options.addClasses ) { 80 this._addClass( "ui-draggable" ); 81 } 82 this._setHandleClassName(); 83 84 this._mouseInit(); 85 }, 86 87 _setOption: function( key, value ) { 88 this._super( key, value ); 89 if ( key === "handle" ) { 90 this._removeHandleClassName(); 91 this._setHandleClassName(); 92 } 93 }, 94 95 _destroy: function() { 96 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 97 this.destroyOnClear = true; 98 return; 99 } 100 this._removeHandleClassName(); 101 this._mouseDestroy(); 102 }, 103 104 _mouseCapture: function( event ) { 105 var o = this.options; 106 107 // Among others, prevent a drag on a resizable-handle 108 if ( this.helper || o.disabled || 109 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) { 110 return false; 111 } 112 113 //Quit if we're not on a valid handle 114 this.handle = this._getHandle( event ); 115 if ( !this.handle ) { 116 return false; 117 } 118 119 this._blurActiveElement( event ); 120 121 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 122 123 return true; 124 125 }, 126 127 _blockFrames: function( selector ) { 128 this.iframeBlocks = this.document.find( selector ).map( function() { 129 var iframe = $( this ); 130 131 return $( "<div>" ) 132 .css( "position", "absolute" ) 133 .appendTo( iframe.parent() ) 134 .outerWidth( iframe.outerWidth() ) 135 .outerHeight( iframe.outerHeight() ) 136 .offset( iframe.offset() )[ 0 ]; 137 } ); 138 }, 139 140 _unblockFrames: function() { 141 if ( this.iframeBlocks ) { 142 this.iframeBlocks.remove(); 143 delete this.iframeBlocks; 144 } 145 }, 146 147 _blurActiveElement: function( event ) { 148 var activeElement = this.document[ 0 ].activeElement, 149 target = $( event.target ); 150 151 // Don't blur if the event occurred on an element that is within 152 // the currently focused element 153 // See #10527, #12472 154 if ( target.closest( activeElement ).length ) { 155 return; 156 } 157 158 // Blur any element that currently has focus, see #4261 159 $( activeElement ).trigger( "blur" ); 160 }, 161 162 _mouseStart: function( event ) { 163 164 var o = this.options; 165 166 //Create and append the visible helper 167 this.helper = this._createHelper( event ); 168 169 this._addClass( this.helper, "ui-draggable-dragging" ); 170 171 //Cache the helper size 172 this._cacheHelperProportions(); 173 174 //If ddmanager is used for droppables, set the global draggable 175 if ( $.ui.ddmanager ) { 176 $.ui.ddmanager.current = this; 177 } 178 179 /* 180 * - Position generation - 181 * This block generates everything position related - it's the core of draggables. 182 */ 183 184 //Cache the margins of the original element 185 this._cacheMargins(); 186 187 //Store the helper's css position 188 this.cssPosition = this.helper.css( "position" ); 189 this.scrollParent = this.helper.scrollParent( true ); 190 this.offsetParent = this.helper.offsetParent(); 191 this.hasFixedAncestor = this.helper.parents().filter( function() { 192 return $( this ).css( "position" ) === "fixed"; 193 } ).length > 0; 194 195 //The element's absolute position on the page minus margins 196 this.positionAbs = this.element.offset(); 197 this._refreshOffsets( event ); 198 199 //Generate the original position 200 this.originalPosition = this.position = this._generatePosition( event, false ); 201 this.originalPageX = event.pageX; 202 this.originalPageY = event.pageY; 203 204 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 205 if ( o.cursorAt ) { 206 this._adjustOffsetFromHelper( o.cursorAt ); 207 } 208 209 //Set a containment if given in the options 210 this._setContainment(); 211 212 //Trigger event + callbacks 213 if ( this._trigger( "start", event ) === false ) { 214 this._clear(); 215 return false; 216 } 217 218 //Recache the helper size 219 this._cacheHelperProportions(); 220 221 //Prepare the droppable offsets 222 if ( $.ui.ddmanager && !o.dropBehaviour ) { 223 $.ui.ddmanager.prepareOffsets( this, event ); 224 } 225 226 // Execute the drag once - this causes the helper not to be visible before getting its 227 // correct position 228 this._mouseDrag( event, true ); 229 230 // If the ddmanager is used for droppables, inform the manager that dragging has started 231 // (see #5003) 232 if ( $.ui.ddmanager ) { 233 $.ui.ddmanager.dragStart( this, event ); 234 } 235 236 return true; 237 }, 238 239 _refreshOffsets: function( event ) { 240 this.offset = { 241 top: this.positionAbs.top - this.margins.top, 242 left: this.positionAbs.left - this.margins.left, 243 scroll: false, 244 parent: this._getParentOffset(), 245 relative: this._getRelativeOffset() 246 }; 247 248 this.offset.click = { 249 left: event.pageX - this.offset.left, 250 top: event.pageY - this.offset.top 251 }; 252 }, 253 254 _mouseDrag: function( event, noPropagation ) { 255 256 // reset any necessary cached properties (see #5009) 257 if ( this.hasFixedAncestor ) { 258 this.offset.parent = this._getParentOffset(); 259 } 260 261 //Compute the helpers position 262 this.position = this._generatePosition( event, true ); 263 this.positionAbs = this._convertPositionTo( "absolute" ); 264 265 //Call plugins and callbacks and use the resulting position if something is returned 266 if ( !noPropagation ) { 267 var ui = this._uiHash(); 268 if ( this._trigger( "drag", event, ui ) === false ) { 269 this._mouseUp( new $.Event( "mouseup", event ) ); 270 return false; 271 } 272 this.position = ui.position; 273 } 274 275 this.helper[ 0 ].style.left = this.position.left + "px"; 276 this.helper[ 0 ].style.top = this.position.top + "px"; 277 278 if ( $.ui.ddmanager ) { 279 $.ui.ddmanager.drag( this, event ); 280 } 281 282 return false; 283 }, 284 285 _mouseStop: function( event ) { 286 287 //If we are using droppables, inform the manager about the drop 288 var that = this, 289 dropped = false; 290 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 291 dropped = $.ui.ddmanager.drop( this, event ); 292 } 293 294 //if a drop comes from outside (a sortable) 295 if ( this.dropped ) { 296 dropped = this.dropped; 297 this.dropped = false; 298 } 299 300 if ( ( this.options.revert === "invalid" && !dropped ) || 301 ( this.options.revert === "valid" && dropped ) || 302 this.options.revert === true || ( typeof this.options.revert === "function" && 303 this.options.revert.call( this.element, dropped ) ) 304 ) { 305 $( this.helper ).animate( 306 this.originalPosition, 307 parseInt( this.options.revertDuration, 10 ), 308 function() { 309 if ( that._trigger( "stop", event ) !== false ) { 310 that._clear(); 311 } 312 } 313 ); 314 } else { 315 if ( this._trigger( "stop", event ) !== false ) { 316 this._clear(); 317 } 318 } 319 320 return false; 321 }, 322 323 _mouseUp: function( event ) { 324 this._unblockFrames(); 325 326 // If the ddmanager is used for droppables, inform the manager that dragging has stopped 327 // (see #5003) 328 if ( $.ui.ddmanager ) { 329 $.ui.ddmanager.dragStop( this, event ); 330 } 331 332 // Only need to focus if the event occurred on the draggable itself, see #10527 333 if ( this.handleElement.is( event.target ) ) { 334 335 // The interaction is over; whether or not the click resulted in a drag, 336 // focus the element 337 this.element.trigger( "focus" ); 338 } 339 340 return $.ui.mouse.prototype._mouseUp.call( this, event ); 341 }, 342 343 cancel: function() { 344 345 if ( this.helper.is( ".ui-draggable-dragging" ) ) { 346 this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) ); 347 } else { 348 this._clear(); 349 } 350 351 return this; 352 353 }, 354 355 _getHandle: function( event ) { 356 return this.options.handle ? 357 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 358 true; 359 }, 360 361 _setHandleClassName: function() { 362 this.handleElement = this.options.handle ? 363 this.element.find( this.options.handle ) : this.element; 364 this._addClass( this.handleElement, "ui-draggable-handle" ); 365 }, 366 367 _removeHandleClassName: function() { 368 this._removeClass( this.handleElement, "ui-draggable-handle" ); 369 }, 370 371 _createHelper: function( event ) { 372 373 var o = this.options, 374 helperIsFunction = typeof o.helper === "function", 375 helper = helperIsFunction ? 376 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 377 ( o.helper === "clone" ? 378 this.element.clone().removeAttr( "id" ) : 379 this.element ); 380 381 if ( !helper.parents( "body" ).length ) { 382 helper.appendTo( ( o.appendTo === "parent" ? 383 this.element[ 0 ].parentNode : 384 o.appendTo ) ); 385 } 386 387 // https://bugs.jqueryui.com/ticket/9446 388 // a helper function can return the original element 389 // which wouldn't have been set to relative in _create 390 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 391 this._setPositionRelative(); 392 } 393 394 if ( helper[ 0 ] !== this.element[ 0 ] && 395 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) { 396 helper.css( "position", "absolute" ); 397 } 398 399 return helper; 400 401 }, 402 403 _setPositionRelative: function() { 404 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 405 this.element[ 0 ].style.position = "relative"; 406 } 407 }, 408 409 _adjustOffsetFromHelper: function( obj ) { 410 if ( typeof obj === "string" ) { 411 obj = obj.split( " " ); 412 } 413 if ( Array.isArray( obj ) ) { 414 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 415 } 416 if ( "left" in obj ) { 417 this.offset.click.left = obj.left + this.margins.left; 418 } 419 if ( "right" in obj ) { 420 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 421 } 422 if ( "top" in obj ) { 423 this.offset.click.top = obj.top + this.margins.top; 424 } 425 if ( "bottom" in obj ) { 426 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 427 } 428 }, 429 430 _isRootNode: function( element ) { 431 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 432 }, 433 434 _getParentOffset: function() { 435 436 //Get the offsetParent and cache its position 437 var po = this.offsetParent.offset(), 438 document = this.document[ 0 ]; 439 440 // This is a special case where we need to modify a offset calculated on start, since the 441 // following happened: 442 // 1. The position of the helper is absolute, so it's position is calculated based on the 443 // next positioned parent 444 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 445 // the document, which means that the scroll is included in the initial calculation of the 446 // offset of the parent, and never recalculated upon drag 447 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document && 448 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 449 po.left += this.scrollParent.scrollLeft(); 450 po.top += this.scrollParent.scrollTop(); 451 } 452 453 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 454 po = { top: 0, left: 0 }; 455 } 456 457 return { 458 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 459 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 460 }; 461 462 }, 463 464 _getRelativeOffset: function() { 465 if ( this.cssPosition !== "relative" ) { 466 return { top: 0, left: 0 }; 467 } 468 469 var p = this.element.position(), 470 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 471 472 return { 473 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 474 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 475 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 476 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 477 }; 478 479 }, 480 481 _cacheMargins: function() { 482 this.margins = { 483 left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ), 484 top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ), 485 right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ), 486 bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 ) 487 }; 488 }, 489 490 _cacheHelperProportions: function() { 491 this.helperProportions = { 492 width: this.helper.outerWidth(), 493 height: this.helper.outerHeight() 494 }; 495 }, 496 497 _setContainment: function() { 498 499 var isUserScrollable, c, ce, 500 o = this.options, 501 document = this.document[ 0 ]; 502 503 this.relativeContainer = null; 504 505 if ( !o.containment ) { 506 this.containment = null; 507 return; 508 } 509 510 if ( o.containment === "window" ) { 511 this.containment = [ 512 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 513 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 514 $( window ).scrollLeft() + $( window ).width() - 515 this.helperProportions.width - this.margins.left, 516 $( window ).scrollTop() + 517 ( $( window ).height() || document.body.parentNode.scrollHeight ) - 518 this.helperProportions.height - this.margins.top 519 ]; 520 return; 521 } 522 523 if ( o.containment === "document" ) { 524 this.containment = [ 525 0, 526 0, 527 $( document ).width() - this.helperProportions.width - this.margins.left, 528 ( $( document ).height() || document.body.parentNode.scrollHeight ) - 529 this.helperProportions.height - this.margins.top 530 ]; 531 return; 532 } 533 534 if ( o.containment.constructor === Array ) { 535 this.containment = o.containment; 536 return; 537 } 538 539 if ( o.containment === "parent" ) { 540 o.containment = this.helper[ 0 ].parentNode; 541 } 542 543 c = $( o.containment ); 544 ce = c[ 0 ]; 545 546 if ( !ce ) { 547 return; 548 } 549 550 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 551 552 this.containment = [ 553 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + 554 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 555 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + 556 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 557 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 558 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 559 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 560 this.helperProportions.width - 561 this.margins.left - 562 this.margins.right, 563 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 564 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 565 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 566 this.helperProportions.height - 567 this.margins.top - 568 this.margins.bottom 569 ]; 570 this.relativeContainer = c; 571 }, 572 573 _convertPositionTo: function( d, pos ) { 574 575 if ( !pos ) { 576 pos = this.position; 577 } 578 579 var mod = d === "absolute" ? 1 : -1, 580 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 581 582 return { 583 top: ( 584 585 // The absolute mouse position 586 pos.top + 587 588 // Only for relative positioned nodes: Relative offset from element to offset parent 589 this.offset.relative.top * mod + 590 591 // The offsetParent's offset without borders (offset + border) 592 this.offset.parent.top * mod - 593 ( ( this.cssPosition === "fixed" ? 594 -this.offset.scroll.top : 595 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod ) 596 ), 597 left: ( 598 599 // The absolute mouse position 600 pos.left + 601 602 // Only for relative positioned nodes: Relative offset from element to offset parent 603 this.offset.relative.left * mod + 604 605 // The offsetParent's offset without borders (offset + border) 606 this.offset.parent.left * mod - 607 ( ( this.cssPosition === "fixed" ? 608 -this.offset.scroll.left : 609 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod ) 610 ) 611 }; 612 613 }, 614 615 _generatePosition: function( event, constrainPosition ) { 616 617 var containment, co, top, left, 618 o = this.options, 619 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 620 pageX = event.pageX, 621 pageY = event.pageY; 622 623 // Cache the scroll 624 if ( !scrollIsRootNode || !this.offset.scroll ) { 625 this.offset.scroll = { 626 top: this.scrollParent.scrollTop(), 627 left: this.scrollParent.scrollLeft() 628 }; 629 } 630 631 /* 632 * - Position constraining - 633 * Constrain the position to a mix of grid, containment. 634 */ 635 636 // If we are not dragging yet, we won't check for options 637 if ( constrainPosition ) { 638 if ( this.containment ) { 639 if ( this.relativeContainer ) { 640 co = this.relativeContainer.offset(); 641 containment = [ 642 this.containment[ 0 ] + co.left, 643 this.containment[ 1 ] + co.top, 644 this.containment[ 2 ] + co.left, 645 this.containment[ 3 ] + co.top 646 ]; 647 } else { 648 containment = this.containment; 649 } 650 651 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) { 652 pageX = containment[ 0 ] + this.offset.click.left; 653 } 654 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) { 655 pageY = containment[ 1 ] + this.offset.click.top; 656 } 657 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) { 658 pageX = containment[ 2 ] + this.offset.click.left; 659 } 660 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) { 661 pageY = containment[ 3 ] + this.offset.click.top; 662 } 663 } 664 665 if ( o.grid ) { 666 667 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid 668 // argument errors in IE (see ticket #6950) 669 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY - 670 this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY; 671 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] || 672 top - this.offset.click.top > containment[ 3 ] ) ? 673 top : 674 ( ( top - this.offset.click.top >= containment[ 1 ] ) ? 675 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top; 676 677 left = o.grid[ 0 ] ? this.originalPageX + 678 Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] : 679 this.originalPageX; 680 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] || 681 left - this.offset.click.left > containment[ 2 ] ) ? 682 left : 683 ( ( left - this.offset.click.left >= containment[ 0 ] ) ? 684 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left; 685 } 686 687 if ( o.axis === "y" ) { 688 pageX = this.originalPageX; 689 } 690 691 if ( o.axis === "x" ) { 692 pageY = this.originalPageY; 693 } 694 } 695 696 return { 697 top: ( 698 699 // The absolute mouse position 700 pageY - 701 702 // Click offset (relative to the element) 703 this.offset.click.top - 704 705 // Only for relative positioned nodes: Relative offset from element to offset parent 706 this.offset.relative.top - 707 708 // The offsetParent's offset without borders (offset + border) 709 this.offset.parent.top + 710 ( this.cssPosition === "fixed" ? 711 -this.offset.scroll.top : 712 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 713 ), 714 left: ( 715 716 // The absolute mouse position 717 pageX - 718 719 // Click offset (relative to the element) 720 this.offset.click.left - 721 722 // Only for relative positioned nodes: Relative offset from element to offset parent 723 this.offset.relative.left - 724 725 // The offsetParent's offset without borders (offset + border) 726 this.offset.parent.left + 727 ( this.cssPosition === "fixed" ? 728 -this.offset.scroll.left : 729 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 730 ) 731 }; 732 733 }, 734 735 _clear: function() { 736 this._removeClass( this.helper, "ui-draggable-dragging" ); 737 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) { 738 this.helper.remove(); 739 } 740 this.helper = null; 741 this.cancelHelperRemoval = false; 742 if ( this.destroyOnClear ) { 743 this.destroy(); 744 } 745 }, 746 747 // From now on bulk stuff - mainly helpers 748 749 _trigger: function( type, event, ui ) { 750 ui = ui || this._uiHash(); 751 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 752 753 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 754 if ( /^(drag|start|stop)/.test( type ) ) { 755 this.positionAbs = this._convertPositionTo( "absolute" ); 756 ui.offset = this.positionAbs; 757 } 758 return $.Widget.prototype._trigger.call( this, type, event, ui ); 759 }, 760 761 plugins: {}, 762 763 _uiHash: function() { 764 return { 765 helper: this.helper, 766 position: this.position, 767 originalPosition: this.originalPosition, 768 offset: this.positionAbs 769 }; 770 } 771 772 } ); 773 774 $.ui.plugin.add( "draggable", "connectToSortable", { 775 start: function( event, ui, draggable ) { 776 var uiSortable = $.extend( {}, ui, { 777 item: draggable.element 778 } ); 779 780 draggable.sortables = []; 781 $( draggable.options.connectToSortable ).each( function() { 782 var sortable = $( this ).sortable( "instance" ); 783 784 if ( sortable && !sortable.options.disabled ) { 785 draggable.sortables.push( sortable ); 786 787 // RefreshPositions is called at drag start to refresh the containerCache 788 // which is used in drag. This ensures it's initialized and synchronized 789 // with any changes that might have happened on the page since initialization. 790 sortable.refreshPositions(); 791 sortable._trigger( "activate", event, uiSortable ); 792 } 793 } ); 794 }, 795 stop: function( event, ui, draggable ) { 796 var uiSortable = $.extend( {}, ui, { 797 item: draggable.element 798 } ); 799 800 draggable.cancelHelperRemoval = false; 801 802 $.each( draggable.sortables, function() { 803 var sortable = this; 804 805 if ( sortable.isOver ) { 806 sortable.isOver = 0; 807 808 // Allow this sortable to handle removing the helper 809 draggable.cancelHelperRemoval = true; 810 sortable.cancelHelperRemoval = false; 811 812 // Use _storedCSS To restore properties in the sortable, 813 // as this also handles revert (#9675) since the draggable 814 // may have modified them in unexpected ways (#8809) 815 sortable._storedCSS = { 816 position: sortable.placeholder.css( "position" ), 817 top: sortable.placeholder.css( "top" ), 818 left: sortable.placeholder.css( "left" ) 819 }; 820 821 sortable._mouseStop( event ); 822 823 // Once drag has ended, the sortable should return to using 824 // its original helper, not the shared helper from draggable 825 sortable.options.helper = sortable.options._helper; 826 } else { 827 828 // Prevent this Sortable from removing the helper. 829 // However, don't set the draggable to remove the helper 830 // either as another connected Sortable may yet handle the removal. 831 sortable.cancelHelperRemoval = true; 832 833 sortable._trigger( "deactivate", event, uiSortable ); 834 } 835 } ); 836 }, 837 drag: function( event, ui, draggable ) { 838 $.each( draggable.sortables, function() { 839 var innermostIntersecting = false, 840 sortable = this; 841 842 // Copy over variables that sortable's _intersectsWith uses 843 sortable.positionAbs = draggable.positionAbs; 844 sortable.helperProportions = draggable.helperProportions; 845 sortable.offset.click = draggable.offset.click; 846 847 if ( sortable._intersectsWith( sortable.containerCache ) ) { 848 innermostIntersecting = true; 849 850 $.each( draggable.sortables, function() { 851 852 // Copy over variables that sortable's _intersectsWith uses 853 this.positionAbs = draggable.positionAbs; 854 this.helperProportions = draggable.helperProportions; 855 this.offset.click = draggable.offset.click; 856 857 if ( this !== sortable && 858 this._intersectsWith( this.containerCache ) && 859 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 860 innermostIntersecting = false; 861 } 862 863 return innermostIntersecting; 864 } ); 865 } 866 867 if ( innermostIntersecting ) { 868 869 // If it intersects, we use a little isOver variable and set it once, 870 // so that the move-in stuff gets fired only once. 871 if ( !sortable.isOver ) { 872 sortable.isOver = 1; 873 874 // Store draggable's parent in case we need to reappend to it later. 875 draggable._parent = ui.helper.parent(); 876 877 sortable.currentItem = ui.helper 878 .appendTo( sortable.element ) 879 .data( "ui-sortable-item", true ); 880 881 // Store helper option to later restore it 882 sortable.options._helper = sortable.options.helper; 883 884 sortable.options.helper = function() { 885 return ui.helper[ 0 ]; 886 }; 887 888 // Fire the start events of the sortable with our passed browser event, 889 // and our own helper (so it doesn't create a new one) 890 event.target = sortable.currentItem[ 0 ]; 891 sortable._mouseCapture( event, true ); 892 sortable._mouseStart( event, true, true ); 893 894 // Because the browser event is way off the new appended portlet, 895 // modify necessary variables to reflect the changes 896 sortable.offset.click.top = draggable.offset.click.top; 897 sortable.offset.click.left = draggable.offset.click.left; 898 sortable.offset.parent.left -= draggable.offset.parent.left - 899 sortable.offset.parent.left; 900 sortable.offset.parent.top -= draggable.offset.parent.top - 901 sortable.offset.parent.top; 902 903 draggable._trigger( "toSortable", event ); 904 905 // Inform draggable that the helper is in a valid drop zone, 906 // used solely in the revert option to handle "valid/invalid". 907 draggable.dropped = sortable.element; 908 909 // Need to refreshPositions of all sortables in the case that 910 // adding to one sortable changes the location of the other sortables (#9675) 911 $.each( draggable.sortables, function() { 912 this.refreshPositions(); 913 } ); 914 915 // Hack so receive/update callbacks work (mostly) 916 draggable.currentItem = draggable.element; 917 sortable.fromOutside = draggable; 918 } 919 920 if ( sortable.currentItem ) { 921 sortable._mouseDrag( event ); 922 923 // Copy the sortable's position because the draggable's can potentially reflect 924 // a relative position, while sortable is always absolute, which the dragged 925 // element has now become. (#8809) 926 ui.position = sortable.position; 927 } 928 } else { 929 930 // If it doesn't intersect with the sortable, and it intersected before, 931 // we fake the drag stop of the sortable, but make sure it doesn't remove 932 // the helper by using cancelHelperRemoval. 933 if ( sortable.isOver ) { 934 935 sortable.isOver = 0; 936 sortable.cancelHelperRemoval = true; 937 938 // Calling sortable's mouseStop would trigger a revert, 939 // so revert must be temporarily false until after mouseStop is called. 940 sortable.options._revert = sortable.options.revert; 941 sortable.options.revert = false; 942 943 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 944 sortable._mouseStop( event, true ); 945 946 // Restore sortable behaviors that were modfied 947 // when the draggable entered the sortable area (#9481) 948 sortable.options.revert = sortable.options._revert; 949 sortable.options.helper = sortable.options._helper; 950 951 if ( sortable.placeholder ) { 952 sortable.placeholder.remove(); 953 } 954 955 // Restore and recalculate the draggable's offset considering the sortable 956 // may have modified them in unexpected ways. (#8809, #10669) 957 ui.helper.appendTo( draggable._parent ); 958 draggable._refreshOffsets( event ); 959 ui.position = draggable._generatePosition( event, true ); 960 961 draggable._trigger( "fromSortable", event ); 962 963 // Inform draggable that the helper is no longer in a valid drop zone 964 draggable.dropped = false; 965 966 // Need to refreshPositions of all sortables just in case removing 967 // from one sortable changes the location of other sortables (#9675) 968 $.each( draggable.sortables, function() { 969 this.refreshPositions(); 970 } ); 971 } 972 } 973 } ); 974 } 975 } ); 976 977 $.ui.plugin.add( "draggable", "cursor", { 978 start: function( event, ui, instance ) { 979 var t = $( "body" ), 980 o = instance.options; 981 982 if ( t.css( "cursor" ) ) { 983 o._cursor = t.css( "cursor" ); 984 } 985 t.css( "cursor", o.cursor ); 986 }, 987 stop: function( event, ui, instance ) { 988 var o = instance.options; 989 if ( o._cursor ) { 990 $( "body" ).css( "cursor", o._cursor ); 991 } 992 } 993 } ); 994 995 $.ui.plugin.add( "draggable", "opacity", { 996 start: function( event, ui, instance ) { 997 var t = $( ui.helper ), 998 o = instance.options; 999 if ( t.css( "opacity" ) ) { 1000 o._opacity = t.css( "opacity" ); 1001 } 1002 t.css( "opacity", o.opacity ); 1003 }, 1004 stop: function( event, ui, instance ) { 1005 var o = instance.options; 1006 if ( o._opacity ) { 1007 $( ui.helper ).css( "opacity", o._opacity ); 1008 } 1009 } 1010 } ); 1011 1012 $.ui.plugin.add( "draggable", "scroll", { 1013 start: function( event, ui, i ) { 1014 if ( !i.scrollParentNotHidden ) { 1015 i.scrollParentNotHidden = i.helper.scrollParent( false ); 1016 } 1017 1018 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && 1019 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 1020 i.overflowOffset = i.scrollParentNotHidden.offset(); 1021 } 1022 }, 1023 drag: function( event, ui, i ) { 1024 1025 var o = i.options, 1026 scrolled = false, 1027 scrollParent = i.scrollParentNotHidden[ 0 ], 1028 document = i.document[ 0 ]; 1029 1030 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 1031 if ( !o.axis || o.axis !== "x" ) { 1032 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < 1033 o.scrollSensitivity ) { 1034 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 1035 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 1036 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 1037 } 1038 } 1039 1040 if ( !o.axis || o.axis !== "y" ) { 1041 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < 1042 o.scrollSensitivity ) { 1043 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 1044 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 1045 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 1046 } 1047 } 1048 1049 } else { 1050 1051 if ( !o.axis || o.axis !== "x" ) { 1052 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) { 1053 scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed ); 1054 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) < 1055 o.scrollSensitivity ) { 1056 scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed ); 1057 } 1058 } 1059 1060 if ( !o.axis || o.axis !== "y" ) { 1061 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) { 1062 scrolled = $( document ).scrollLeft( 1063 $( document ).scrollLeft() - o.scrollSpeed 1064 ); 1065 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) < 1066 o.scrollSensitivity ) { 1067 scrolled = $( document ).scrollLeft( 1068 $( document ).scrollLeft() + o.scrollSpeed 1069 ); 1070 } 1071 } 1072 1073 } 1074 1075 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { 1076 $.ui.ddmanager.prepareOffsets( i, event ); 1077 } 1078 1079 } 1080 } ); 1081 1082 $.ui.plugin.add( "draggable", "snap", { 1083 start: function( event, ui, i ) { 1084 1085 var o = i.options; 1086 1087 i.snapElements = []; 1088 1089 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap ) 1090 .each( function() { 1091 var $t = $( this ), 1092 $o = $t.offset(); 1093 if ( this !== i.element[ 0 ] ) { 1094 i.snapElements.push( { 1095 item: this, 1096 width: $t.outerWidth(), height: $t.outerHeight(), 1097 top: $o.top, left: $o.left 1098 } ); 1099 } 1100 } ); 1101 1102 }, 1103 drag: function( event, ui, inst ) { 1104 1105 var ts, bs, ls, rs, l, r, t, b, i, first, 1106 o = inst.options, 1107 d = o.snapTolerance, 1108 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 1109 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 1110 1111 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) { 1112 1113 l = inst.snapElements[ i ].left - inst.margins.left; 1114 r = l + inst.snapElements[ i ].width; 1115 t = inst.snapElements[ i ].top - inst.margins.top; 1116 b = t + inst.snapElements[ i ].height; 1117 1118 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || 1119 !$.contains( inst.snapElements[ i ].item.ownerDocument, 1120 inst.snapElements[ i ].item ) ) { 1121 if ( inst.snapElements[ i ].snapping ) { 1122 if ( inst.options.snap.release ) { 1123 inst.options.snap.release.call( 1124 inst.element, 1125 event, 1126 $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } ) 1127 ); 1128 } 1129 } 1130 inst.snapElements[ i ].snapping = false; 1131 continue; 1132 } 1133 1134 if ( o.snapMode !== "inner" ) { 1135 ts = Math.abs( t - y2 ) <= d; 1136 bs = Math.abs( b - y1 ) <= d; 1137 ls = Math.abs( l - x2 ) <= d; 1138 rs = Math.abs( r - x1 ) <= d; 1139 if ( ts ) { 1140 ui.position.top = inst._convertPositionTo( "relative", { 1141 top: t - inst.helperProportions.height, 1142 left: 0 1143 } ).top; 1144 } 1145 if ( bs ) { 1146 ui.position.top = inst._convertPositionTo( "relative", { 1147 top: b, 1148 left: 0 1149 } ).top; 1150 } 1151 if ( ls ) { 1152 ui.position.left = inst._convertPositionTo( "relative", { 1153 top: 0, 1154 left: l - inst.helperProportions.width 1155 } ).left; 1156 } 1157 if ( rs ) { 1158 ui.position.left = inst._convertPositionTo( "relative", { 1159 top: 0, 1160 left: r 1161 } ).left; 1162 } 1163 } 1164 1165 first = ( ts || bs || ls || rs ); 1166 1167 if ( o.snapMode !== "outer" ) { 1168 ts = Math.abs( t - y1 ) <= d; 1169 bs = Math.abs( b - y2 ) <= d; 1170 ls = Math.abs( l - x1 ) <= d; 1171 rs = Math.abs( r - x2 ) <= d; 1172 if ( ts ) { 1173 ui.position.top = inst._convertPositionTo( "relative", { 1174 top: t, 1175 left: 0 1176 } ).top; 1177 } 1178 if ( bs ) { 1179 ui.position.top = inst._convertPositionTo( "relative", { 1180 top: b - inst.helperProportions.height, 1181 left: 0 1182 } ).top; 1183 } 1184 if ( ls ) { 1185 ui.position.left = inst._convertPositionTo( "relative", { 1186 top: 0, 1187 left: l 1188 } ).left; 1189 } 1190 if ( rs ) { 1191 ui.position.left = inst._convertPositionTo( "relative", { 1192 top: 0, 1193 left: r - inst.helperProportions.width 1194 } ).left; 1195 } 1196 } 1197 1198 if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) { 1199 if ( inst.options.snap.snap ) { 1200 inst.options.snap.snap.call( 1201 inst.element, 1202 event, 1203 $.extend( inst._uiHash(), { 1204 snapItem: inst.snapElements[ i ].item 1205 } ) ); 1206 } 1207 } 1208 inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first ); 1209 1210 } 1211 1212 } 1213 } ); 1214 1215 $.ui.plugin.add( "draggable", "stack", { 1216 start: function( event, ui, instance ) { 1217 var min, 1218 o = instance.options, 1219 group = $.makeArray( $( o.stack ) ).sort( function( a, b ) { 1220 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) - 1221 ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 ); 1222 } ); 1223 1224 if ( !group.length ) { 1225 return; 1226 } 1227 1228 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0; 1229 $( group ).each( function( i ) { 1230 $( this ).css( "zIndex", min + i ); 1231 } ); 1232 this.css( "zIndex", ( min + group.length ) ); 1233 } 1234 } ); 1235 1236 $.ui.plugin.add( "draggable", "zIndex", { 1237 start: function( event, ui, instance ) { 1238 var t = $( ui.helper ), 1239 o = instance.options; 1240 1241 if ( t.css( "zIndex" ) ) { 1242 o._zIndex = t.css( "zIndex" ); 1243 } 1244 t.css( "zIndex", o.zIndex ); 1245 }, 1246 stop: function( event, ui, instance ) { 1247 var o = instance.options; 1248 1249 if ( o._zIndex ) { 1250 $( ui.helper ).css( "zIndex", o._zIndex ); 1251 } 1252 } 1253 } ); 1254 1255 return $.ui.draggable; 1256 1257 } );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sat Aug 1 08:20:18 2026 | Cross-referenced by PHPXref |