Skip to content

Commit c8e1370

Browse files
committed
Draggable: Scrollbars being handled when scrollParent is document
1 parent e43ce91 commit c8e1370

File tree

1 file changed

+77
-30
lines changed

1 file changed

+77
-30
lines changed

ui/jquery.ui.draggable.js

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ $.widget( "ui.draggable", {
1919

2020
options: {
2121

22+
scrollSpeed: 20,
23+
scrollSensitivity:20,
2224
helper: false
2325

2426
},
@@ -47,43 +49,48 @@ $.widget( "ui.draggable", {
4749

4850
this.scrollParent = this.element.scrollParent();
4951

52+
// Offset of scrollParent, used for auto-scrolling
53+
this.overflowOffset = {};
54+
55+
// Height of scrollParent, used for auto-scrolling
56+
this.overflowHeight = 0;
57+
58+
// Width of scrollParent, used for auto-scrolling
59+
this.overflowWidth = 0;
60+
5061
// Static position elements can"t be moved with top/left
5162
if ( this.element.css( "position" ) === "static" ) {
5263
this.element.css( "position", "relative" );
5364
}
54-
65+
5566
// Using proxy to avoid anon functions using self to pass "this" along
5667
this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) );
5768

5869
},
59-
70+
6071
_usingHelper : function() {
6172
return ( this.options.helper === true || typeof this.options.helper === 'function' );
6273
},
6374

6475
_setPosition: function() {
6576

66-
var left, top, position, cssPosition;
77+
var left, top, position,
78+
scrollTop = this.scrollParent.scrollTop(),
79+
scrollLeft = this.scrollParent.scrollLeft();
6780

6881
// Helper is appended to body so offset of element is all that's needed
6982
if ( this._usingHelper() ) {
7083
return this.element.offset();
7184
}
7285

73-
cssPosition = this.dragEl.css( "position" );;
74-
7586
// If fixed or absolute
76-
if ( cssPosition !== "relative" ) {
87+
if ( this.cssPosition !== "relative" ) {
7788

7889
position = this.dragEl.position();
7990

80-
if ( cssPosition === "absolute" ) {
81-
return position;
82-
}
83-
84-
// Take into account scrollbar for fixed position
85-
position.top = position.top - this.scrollParent.scrollTop();
86-
position.left = position.left - this.scrollParent.scrollLeft();
91+
// Take into account scrollbar
92+
position.top = position.top - scrollTop;
93+
position.left = position.left - scrollLeft
8794

8895
return position;
8996

@@ -100,20 +107,22 @@ $.widget( "ui.draggable", {
100107

101108
return {
102109

103-
left: left,
104-
top: top
110+
left: left - scrollLeft,
111+
top: top - scrollTop
105112

106113
};
107114

108115
},
109116

110117
_mouseDown: function( event ) {
111-
118+
112119
// Stop browser from highlighting, among other things
113120
event.preventDefault();
114121

115122
// The actual dragging element, should always be a jQuery object
116123
this.dragEl = this.element;
124+
125+
this.cssPosition = this.dragEl.css( "position" );
117126

118127
// Helper required, so clone, hide, and set reference
119128
if ( this._usingHelper() ) {
@@ -131,16 +140,16 @@ $.widget( "ui.draggable", {
131140
}
132141

133142
} else {
134-
143+
135144
this.dragEl = this.options.helper();
136-
145+
137146
// If function was passed, it should return a DOMElement
138147
if ( typeof this.dragEl.nodeType !== 'number' ) {
139148
throw "Helper function must return a DOMElement";
140149
}
141-
150+
142151
this.dragEl = $( this.dragEl );
143-
152+
144153
}
145154

146155
// Automatically make helper absolute
@@ -166,10 +175,15 @@ $.widget( "ui.draggable", {
166175
top: event.clientY
167176
};
168177

178+
// Cache the offset of scrollParent
179+
this.overflowOffset = this.scrollParent.offset();
180+
this.overflowHeight = ( this.scrollParent[0] === document ) ? $(window).height() : this.scrollParent.height();
181+
this.overflowWidth = ( this.scrollParent[0] === document ) ? $(window).width() : this.scrollParent.width();
182+
169183
this._trigger( "start", event );
170184

171-
$(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) );
172-
$(document).bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) );
185+
$(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) )
186+
.bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) );
173187

174188

175189
// Set the helper up by actual element
@@ -189,11 +203,11 @@ $.widget( "ui.draggable", {
189203
},
190204

191205
_mouseMove: function( event ) {
192-
206+
193207
var leftDiff = event.clientX - this.startCoords.left,
194-
topDiff = event.clientY - this.startCoords.top,
195-
newLeft = leftDiff + this.startPosition.left,
196-
newTop = topDiff + this.startPosition.top;
208+
topDiff = event.clientY - this.startCoords.top,
209+
newLeft = leftDiff + this.startPosition.left,
210+
newTop = topDiff + this.startPosition.top;
197211

198212
this.position = {
199213
left: newLeft,
@@ -213,18 +227,51 @@ $.widget( "ui.draggable", {
213227
this.offset = this.dragEl.offset();
214228

215229
}
230+
231+
newLeft = this.position.left;
232+
newTop = this.position.top;
233+
234+
if ( this.cssPosition !== 'fixed' ) {
235+
236+
newLeft = newLeft + this.scrollParent.scrollLeft();
237+
newTop = newTop + this.scrollParent.scrollTop();
238+
239+
}
216240

217241
this.dragEl.css({
218242

219-
left: this.position.left + "px",
220-
top: this.position.top + "px"
243+
left: newLeft + "px",
244+
top: newTop + "px"
221245

222246
});
247+
248+
// Scroll the scrollParent, if needed
249+
this._handleScrolling( event );
250+
251+
},
252+
253+
_handleScrolling: function( event ) {
254+
255+
var doc = $(document),
256+
scrollTop = doc.scrollTop(),
257+
scrollLeft = doc.scrollLeft();
258+
259+
// Handle vertical scrolling
260+
if ( ( ( this.overflowHeight + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) {
261+
doc.scrollTop( scrollTop + this.options.scrollSpeed );
262+
}
263+
264+
// Handle horizontal scrolling
265+
if ( ( ( this.overflowWidth + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) {
266+
doc.scrollLeft( scrollLeft + this.options.scrollSpeed );
267+
}
223268

224269
},
225270

226271
_mouseUp: function( event ) {
227272

273+
var doc = $(document);
274+
228275
this._trigger( "stop", event );
229276

230277
this.startCoords = {};
@@ -233,8 +280,8 @@ $.widget( "ui.draggable", {
233280
this.dragEl.remove();
234281
}
235282

236-
$(document).unbind( "mousemove." + this.widgetName );
237-
$(document).unbind( "mouseup." + this.widgetName );
283+
doc.unbind( "mousemove." + this.widgetName );
284+
doc.unbind( "mouseup." + this.widgetName );
238285

239286
},
240287

0 commit comments

Comments
 (0)