2008-06-04 02:34:33 +00:00
|
|
|
/*
|
2011-10-14 18:19:04 +00:00
|
|
|
* jQuery UI Draggable @VERSION
|
2008-06-04 02:34:33 +00:00
|
|
|
*
|
2011-01-17 14:13:18 +00:00
|
|
|
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
2010-07-09 13:01:04 +00:00
|
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
|
|
* http://jquery.org/license
|
2008-11-10 05:18:20 +00:00
|
|
|
*
|
2011-10-14 18:19:04 +00:00
|
|
|
* http://docs.jquery.com/UI/Draggable
|
2008-06-04 02:34:33 +00:00
|
|
|
*
|
|
|
|
* Depends:
|
2009-09-17 10:39:12 +00:00
|
|
|
* jquery.ui.core.js
|
2009-12-22 19:51:24 +00:00
|
|
|
* jquery.ui.widget.js
|
2008-06-04 02:34:33 +00:00
|
|
|
*/
|
2010-07-13 13:57:58 +00:00
|
|
|
(function( $, undefined ) {
|
2008-06-04 02:34:33 +00:00
|
|
|
|
2011-11-23 17:03:09 +00:00
|
|
|
$.widget( "ui.draggable", $.ui.interaction, {
|
2011-10-14 18:19:04 +00:00
|
|
|
version: "@VERSION",
|
2010-02-05 03:03:50 +00:00
|
|
|
widgetEventPrefix: "drag",
|
2011-09-28 01:33:38 +00:00
|
|
|
|
2010-01-07 03:19:50 +00:00
|
|
|
options: {
|
2011-11-18 00:48:04 +00:00
|
|
|
helper: null,
|
|
|
|
// TODO: remove scroll options
|
2011-10-14 18:19:04 +00:00
|
|
|
scrollSensitivity: 20,
|
2011-11-18 00:48:04 +00:00
|
|
|
scrollSpeed: 20
|
2008-11-21 04:01:33 +00:00
|
|
|
},
|
|
|
|
|
2011-10-14 18:19:04 +00:00
|
|
|
// dragEl: element being dragged (original or helper)
|
2011-10-26 01:54:03 +00:00
|
|
|
// position: final CSS position of dragEl
|
2011-10-14 18:19:04 +00:00
|
|
|
// offset: offset of dragEl
|
|
|
|
// startCoords: clientX/Y of the mousedown (offset of pointer)
|
|
|
|
// startPosition: CSS position prior to drag start
|
|
|
|
// startOffset: offset prior to drag start
|
2011-10-26 01:54:03 +00:00
|
|
|
// tempPosition: overridable CSS position of dragEl
|
2011-10-14 18:19:04 +00:00
|
|
|
// overflowOffset: offset of scroll parent
|
2011-10-26 01:54:03 +00:00
|
|
|
// overflow: object containing width and height keys of scroll parent
|
2008-11-21 04:01:33 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
_create: function() {
|
2011-11-23 17:32:55 +00:00
|
|
|
this._super();
|
2011-10-14 18:19:04 +00:00
|
|
|
// Static position elements can't be moved with top/left
|
2011-09-28 01:33:38 +00:00
|
|
|
if ( this.element.css( "position" ) === "static" ) {
|
|
|
|
this.element.css( "position", "relative" );
|
|
|
|
}
|
2011-10-01 16:38:48 +00:00
|
|
|
},
|
2008-11-23 17:42:24 +00:00
|
|
|
|
2011-10-14 18:19:04 +00:00
|
|
|
_getPosition: function() {
|
2011-11-06 21:39:17 +00:00
|
|
|
var left, top, position, offset,
|
2011-10-14 18:19:04 +00:00
|
|
|
scrollTop = this.scrollParent.scrollTop(),
|
|
|
|
scrollLeft = this.scrollParent.scrollLeft();
|
2008-11-28 15:43:32 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
// If fixed or absolute
|
2011-10-09 04:54:47 +00:00
|
|
|
if ( this.cssPosition !== "relative" ) {
|
2011-09-28 01:33:38 +00:00
|
|
|
position = this.dragEl.position();
|
2008-11-28 15:43:32 +00:00
|
|
|
|
2011-10-09 04:54:47 +00:00
|
|
|
// Take into account scrollbar
|
2011-10-14 18:19:04 +00:00
|
|
|
position.top -= scrollTop;
|
2011-11-06 21:39:17 +00:00
|
|
|
position.left -= scrollLeft;
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
return position;
|
2011-10-01 16:38:48 +00:00
|
|
|
}
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-10-14 18:19:04 +00:00
|
|
|
// When using relative, css values are checked
|
2011-11-23 14:03:02 +00:00
|
|
|
// Otherwise the position wouldn't account for padding on ancestors
|
2011-09-28 01:33:38 +00:00
|
|
|
left = this.dragEl.css( "left" );
|
2011-10-01 16:05:36 +00:00
|
|
|
top = this.dragEl.css( "top" );
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-11-23 14:03:02 +00:00
|
|
|
// Webkit will give back auto if there is no explicit value
|
2011-10-01 16:05:36 +00:00
|
|
|
left = ( left === "auto" ) ? 0: parseInt( left, 10 );
|
|
|
|
top = ( top === "auto" ) ? 0: parseInt( top, 10 );
|
2011-09-28 01:33:38 +00:00
|
|
|
|
|
|
|
return {
|
2011-10-09 04:54:47 +00:00
|
|
|
left: left - scrollLeft,
|
|
|
|
top: top - scrollTop
|
2011-09-28 01:33:38 +00:00
|
|
|
};
|
|
|
|
},
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
_handleScrolling: function( event ) {
|
|
|
|
var scrollTop = this.scrollParent.scrollTop(),
|
|
|
|
scrollLeft = this.scrollParent.scrollLeft();
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// overflowOffset is only set when scrollParent is not doc/html
|
|
|
|
if ( !this.overflowOffset ) {
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Handle vertical scrolling
|
|
|
|
if ( ( ( this.overflow.height + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) {
|
|
|
|
this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed );
|
|
|
|
}
|
|
|
|
else if ( event.pageY < ( scrollTop + this.options.scrollSensitivity ) ) {
|
|
|
|
this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed );
|
|
|
|
}
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Handle horizontal scrolling
|
|
|
|
if ( ( ( this.overflow.width + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) {
|
|
|
|
this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed );
|
|
|
|
}
|
|
|
|
else if ( event.pageX < ( scrollLeft + this.options.scrollSensitivity ) ) {
|
|
|
|
this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Handle vertical scrolling
|
|
|
|
if ( ( event.pageY + this.options.scrollSensitivity ) > ( this.overflow.height + this.overflowOffset.top ) ) {
|
|
|
|
this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed );
|
|
|
|
}
|
|
|
|
else if ( ( event.pageY - this.options.scrollSensitivity ) < this.overflowOffset.top ) {
|
|
|
|
this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed );
|
|
|
|
}
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Handle horizontal scrolling
|
|
|
|
if ( ( event.pageX + this.options.scrollSensitivity ) > ( this.overflow.width + this.overflowOffset.left ) ) {
|
|
|
|
this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed );
|
|
|
|
}
|
|
|
|
else if ( ( event.pageX - this.options.scrollSensitivity ) < this.overflowOffset.left ) {
|
|
|
|
this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2011-11-23 17:03:09 +00:00
|
|
|
_start: function( event ) {
|
2011-11-18 00:48:04 +00:00
|
|
|
var newLeft, newTop;
|
2011-10-26 01:54:03 +00:00
|
|
|
|
2011-10-01 16:38:48 +00:00
|
|
|
// The actual dragging element, should always be a jQuery object
|
2011-09-28 01:33:38 +00:00
|
|
|
this.dragEl = this.element;
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-10-14 18:19:04 +00:00
|
|
|
// Helper required
|
|
|
|
if ( this.options.helper ) {
|
|
|
|
// clone
|
2011-10-01 16:38:48 +00:00
|
|
|
if ( this.options.helper === true ) {
|
2011-10-17 12:26:12 +00:00
|
|
|
this.dragEl = this.element.clone()
|
|
|
|
.removeAttr( "id" )
|
|
|
|
.find( "[id]" )
|
|
|
|
.removeAttr( "id" )
|
|
|
|
.end();
|
2011-10-01 16:38:48 +00:00
|
|
|
} else {
|
2011-10-14 18:19:04 +00:00
|
|
|
// TODO: figure out the signature for this; see #4957
|
|
|
|
this.dragEl = $( this.options.helper() );
|
2011-10-01 16:38:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.dragEl
|
2011-10-14 18:19:04 +00:00
|
|
|
// TODO: should we move this to the stylesheet and use a class?
|
|
|
|
.css( "position", "absolute" )
|
2011-11-06 21:39:17 +00:00
|
|
|
.appendTo( this.document[0].body )
|
2011-10-14 18:19:04 +00:00
|
|
|
.offset( this.element.offset() );
|
2011-10-01 16:38:48 +00:00
|
|
|
}
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
this.cssPosition = this.dragEl.css( "position" );
|
2011-11-23 14:03:02 +00:00
|
|
|
this.scrollParent = this.element.scrollParent();
|
2008-06-04 02:34:33 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
// Cache starting absolute and relative positions
|
2011-10-14 18:19:04 +00:00
|
|
|
this.startPosition = this._getPosition();
|
2011-10-01 16:05:36 +00:00
|
|
|
this.startOffset = this.dragEl.offset();
|
2008-11-21 04:01:33 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
// Cache current position and offset
|
|
|
|
this.position = $.extend( {}, this.startPosition );
|
2011-10-01 16:05:36 +00:00
|
|
|
this.offset = $.extend( {}, this.startOffset );
|
2009-01-22 13:10:18 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
this.startCoords = {
|
2011-10-01 16:05:36 +00:00
|
|
|
left: event.clientX,
|
|
|
|
top: event.clientY
|
2011-09-28 01:33:38 +00:00
|
|
|
};
|
2009-01-22 13:10:18 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Cache the offset of scrollParent, if required for _handleScrolling
|
2011-11-06 21:39:17 +00:00
|
|
|
if ( this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== 'HTML') {
|
2011-10-26 01:54:03 +00:00
|
|
|
this.overflowOffset = this.scrollParent.offset();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.overflow = {};
|
|
|
|
|
2011-11-06 21:39:17 +00:00
|
|
|
this.overflow.height = ( this.scrollParent[0] === this.document[0] ) ?
|
|
|
|
this.window.height() : this.scrollParent.height();
|
2011-10-26 01:54:03 +00:00
|
|
|
|
2011-11-06 21:39:17 +00:00
|
|
|
this.overflow.width = ( this.scrollParent[0] === this.document[0] ) ?
|
|
|
|
this.window.width() : this.scrollParent.width();
|
2011-10-14 18:19:04 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
this._preparePosition( event );
|
|
|
|
|
|
|
|
// If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes
|
2011-11-18 00:48:04 +00:00
|
|
|
if ( this._trigger( "start", event, this._uiHash() ) === false ) {
|
2011-11-23 17:03:09 +00:00
|
|
|
return false;
|
2011-10-26 01:54:03 +00:00
|
|
|
}
|
|
|
|
|
2011-11-18 00:48:04 +00:00
|
|
|
this._blockFrames();
|
2011-10-26 01:54:03 +00:00
|
|
|
this._setCss( event );
|
2011-09-28 01:33:38 +00:00
|
|
|
},
|
2008-11-21 04:01:33 +00:00
|
|
|
|
2011-11-23 17:03:09 +00:00
|
|
|
_move: function( event ) {
|
2011-11-18 00:48:04 +00:00
|
|
|
var newLeft, newTop;
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
this._preparePosition( event );
|
|
|
|
|
|
|
|
// If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes
|
2011-11-18 00:48:04 +00:00
|
|
|
if ( this._trigger( "drag", event, this._uiHash() ) === false ) {
|
2011-10-26 01:54:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._setCss( event );
|
|
|
|
|
|
|
|
// Scroll the scrollParent, if needed
|
|
|
|
this._handleScrolling( event );
|
|
|
|
},
|
|
|
|
|
2011-11-23 17:03:09 +00:00
|
|
|
_stop: function( event ) {
|
2011-10-26 01:54:03 +00:00
|
|
|
this._preparePosition( event );
|
|
|
|
|
|
|
|
// If user stops propagation, leave helper there, disallow any CSS changes
|
2011-11-18 00:48:04 +00:00
|
|
|
if ( this._trigger( "stop", event, this._uiHash() ) === false ) {
|
2011-10-26 01:54:03 +00:00
|
|
|
this._setCss( event );
|
|
|
|
if ( this.options.helper ) {
|
|
|
|
this.dragEl.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-18 00:48:04 +00:00
|
|
|
this._unblockFrames();
|
2011-10-26 01:54:03 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Uses event to determine new position of draggable, before any override from callbacks
|
|
|
|
_preparePosition: function( event ) {
|
2011-09-28 01:33:38 +00:00
|
|
|
var leftDiff = event.clientX - this.startCoords.left,
|
2011-10-14 18:19:04 +00:00
|
|
|
topDiff = event.clientY - this.startCoords.top,
|
|
|
|
newLeft = leftDiff + this.startPosition.left,
|
|
|
|
newTop = topDiff + this.startPosition.top;
|
2008-11-21 04:01:33 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Save off new values for .css() in various callbacks using this function
|
2011-09-28 01:33:38 +00:00
|
|
|
this.position = {
|
2011-10-01 16:05:36 +00:00
|
|
|
left: newLeft,
|
|
|
|
top: newTop
|
2011-09-28 01:33:38 +00:00
|
|
|
};
|
2008-11-21 04:01:33 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Save off values to compare user override against automatic coordinates
|
|
|
|
this.tempPosition = {
|
|
|
|
left: newLeft,
|
|
|
|
top: newTop
|
2011-11-06 21:39:17 +00:00
|
|
|
};
|
2011-11-18 00:48:04 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
// Refresh offset cache with new positions
|
2011-11-13 22:14:19 +00:00
|
|
|
this.offset.left = this.startOffset.left + leftDiff;
|
|
|
|
this.offset.top = this.startOffset.top + topDiff;
|
2011-10-26 01:54:03 +00:00
|
|
|
},
|
2008-06-04 02:34:33 +00:00
|
|
|
|
2011-10-26 01:54:03 +00:00
|
|
|
// Places draggable where mouse or user from callback indicates
|
|
|
|
_setCss: function( event ) {
|
|
|
|
var newLeft, newTop;
|
2008-06-04 02:34:33 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
// User overriding left/top so shortcut math is no longer valid
|
2011-10-26 01:54:03 +00:00
|
|
|
if ( this.tempPosition.left !== this.position.left || this.tempPosition.top !== this.position.top ) {
|
2011-10-14 18:19:04 +00:00
|
|
|
// TODO: can we just store the previous offset values
|
|
|
|
// and not go through .offset()?
|
2011-09-28 01:33:38 +00:00
|
|
|
// refresh offset using slower functions
|
2011-10-01 16:05:36 +00:00
|
|
|
this.offset = this.dragEl.offset();
|
2011-09-28 01:33:38 +00:00
|
|
|
}
|
2011-10-14 18:19:04 +00:00
|
|
|
|
2011-10-09 04:54:47 +00:00
|
|
|
newLeft = this.position.left;
|
|
|
|
newTop = this.position.top;
|
2011-10-14 18:19:04 +00:00
|
|
|
|
|
|
|
// TODO: does this work with nested scrollable parents?
|
|
|
|
if ( this.cssPosition !== "fixed" ) {
|
2011-10-09 04:54:47 +00:00
|
|
|
newLeft = newLeft + this.scrollParent.scrollLeft();
|
|
|
|
newTop = newTop + this.scrollParent.scrollTop();
|
|
|
|
}
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-09-28 01:33:38 +00:00
|
|
|
this.dragEl.css({
|
2011-11-18 00:48:04 +00:00
|
|
|
left: newLeft,
|
|
|
|
top: newTop
|
2011-09-28 01:33:38 +00:00
|
|
|
});
|
|
|
|
},
|
2008-11-10 05:18:20 +00:00
|
|
|
|
2011-10-14 18:19:04 +00:00
|
|
|
_uiHash: function( event ) {
|
2011-11-06 21:20:56 +00:00
|
|
|
var ret = {
|
2011-11-13 22:14:19 +00:00
|
|
|
position: this.position,
|
|
|
|
offset: this.offset
|
2008-06-04 02:34:33 +00:00
|
|
|
};
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-11-18 00:48:04 +00:00
|
|
|
// TODO: should we always set the helper?
|
2011-11-06 21:20:56 +00:00
|
|
|
if ( this.options.helper ) {
|
|
|
|
ret.helper = this.dragEl;
|
|
|
|
}
|
2011-11-06 22:42:35 +00:00
|
|
|
|
2011-11-06 21:20:56 +00:00
|
|
|
return ret;
|
2011-11-06 22:42:35 +00:00
|
|
|
},
|
|
|
|
|
2011-11-23 14:03:02 +00:00
|
|
|
_blockFrames: function() {
|
|
|
|
var body = this.document[0].body;
|
|
|
|
|
|
|
|
this.iframeBlocks = this.document.find( "iframe" ).map(function() {
|
|
|
|
var iframe = $( this ),
|
|
|
|
iframeOffset = iframe.offset();
|
|
|
|
|
|
|
|
return $( "<div>" )
|
|
|
|
.css({
|
|
|
|
position: "absolute",
|
|
|
|
width: iframe.outerWidth(),
|
|
|
|
height: iframe.outerHeight(),
|
|
|
|
top: iframeOffset.top,
|
|
|
|
left: iframeOffset.left
|
|
|
|
})
|
|
|
|
.appendTo( body )[0];
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2011-11-06 22:42:35 +00:00
|
|
|
_unblockFrames: function() {
|
2011-11-18 00:48:04 +00:00
|
|
|
if ( this.iframeBlocks ) {
|
|
|
|
this.iframeBlocks.remove();
|
|
|
|
delete this.iframeBlocks;
|
2011-11-06 22:42:35 +00:00
|
|
|
}
|
2011-09-28 01:33:38 +00:00
|
|
|
}
|
2008-06-04 02:34:33 +00:00
|
|
|
});
|
|
|
|
|
2011-10-14 18:19:04 +00:00
|
|
|
})( jQuery );
|