Skip to content

Commit 1337573

Browse files
committed
Squashed commit of the following:
Draggable: Fixed when cssPosition is being set. Scrolling handles non-doc overflow. _handleScrolling handles scrolling up and left now Made window, doc, and window part of base widget All parts of drag may be stopped via stopPropagation User can now override position of draggable on start, drag, and stop Whitespace fix Moved overflowWidth and overflowHeight into overflow.width and overflow.height
1 parent bc921df commit 1337573

File tree

2 files changed

+133
-44
lines changed

2 files changed

+133
-44
lines changed

ui/jquery.ui.draggable.js

Lines changed: 130 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,16 @@ $.widget( "ui.draggable", {
2424
},
2525

2626
// dragEl: element being dragged (original or helper)
27-
// position: CSS position of dragEl
27+
// position: final CSS position of dragEl
2828
// offset: offset of dragEl
2929
// startCoords: clientX/Y of the mousedown (offset of pointer)
3030
// startPosition: CSS position prior to drag start
3131
// startOffset: offset prior to drag start
32+
// tempPosition: overridable CSS position of dragEl
3233
// overflowOffset: offset of scroll parent
33-
// overflowHeight: height of scroll parent
34-
// overflowWidth: width of scroll parent
34+
// overflow: object containing width and height keys of scroll parent
3535

3636
_create: function() {
37-
// TODO: add these to the base widget
38-
this.doc = $( this.element[0].ownerDocument );
39-
this.win = $( this.doc[0].defaultView );
40-
4137
this.scrollParent = this.element.scrollParent();
4238

4339
// Static position elements can't be moved with top/left
@@ -79,13 +75,62 @@ $.widget( "ui.draggable", {
7975
};
8076
},
8177

78+
_handleScrolling: function( event ) {
79+
// TODO: what is expected behavior of absolute/fixed draggable inside a div having overflow:scroll?
80+
var scrollTop = this.scrollParent.scrollTop(),
81+
scrollLeft = this.scrollParent.scrollLeft();
82+
83+
// overflowOffset is only set when scrollParent is not doc/html
84+
if ( !this.overflowOffset ) {
85+
86+
// Handle vertical scrolling
87+
if ( ( ( this.overflow.height + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) {
88+
this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed );
89+
}
90+
else if ( event.pageY < ( scrollTop + this.options.scrollSensitivity ) ) {
91+
this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed );
92+
}
93+
94+
// Handle horizontal scrolling
95+
if ( ( ( this.overflow.width + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) {
96+
this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed );
97+
}
98+
else if ( event.pageX < ( scrollLeft + this.options.scrollSensitivity ) ) {
99+
this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed );
100+
}
101+
102+
} else {
103+
104+
105+
// Handle vertical scrolling
106+
if ( ( event.pageY + this.options.scrollSensitivity ) > ( this.overflow.height + this.overflowOffset.top ) ) {
107+
this.scrollParent.scrollTop( scrollTop + this.options.scrollSpeed );
108+
}
109+
else if ( ( event.pageY - this.options.scrollSensitivity ) < this.overflowOffset.top ) {
110+
this.scrollParent.scrollTop( scrollTop - this.options.scrollSpeed );
111+
}
112+
113+
// Handle horizontal scrolling
114+
if ( ( event.pageX + this.options.scrollSensitivity ) > ( this.overflow.width + this.overflowOffset.left ) ) {
115+
this.scrollParent.scrollLeft( scrollLeft + this.options.scrollSpeed );
116+
}
117+
else if ( ( event.pageX - this.options.scrollSensitivity ) < this.overflowOffset.left ) {
118+
this.scrollParent.scrollLeft( scrollLeft - this.options.scrollSpeed );
119+
}
120+
121+
122+
}
123+
124+
},
125+
82126
_mouseDown: function( event ) {
127+
var newLeft, newTop;
128+
83129
// Prevent text selection, among other things
84130
event.preventDefault();
85131

86132
// The actual dragging element, should always be a jQuery object
87133
this.dragEl = this.element;
88-
this.cssPosition = this.dragEl.css( "position" );
89134

90135
// Helper required
91136
if ( this.options.helper ) {
@@ -107,6 +152,8 @@ $.widget( "ui.draggable", {
107152
.appendTo( this.doc[0].body )
108153
.offset( this.element.offset() );
109154
}
155+
156+
this.cssPosition = this.dragEl.css( "position" );
110157

111158
// Cache starting absolute and relative positions
112159
this.startPosition = this._getPosition();
@@ -121,16 +168,31 @@ $.widget( "ui.draggable", {
121168
top: event.clientY
122169
};
123170

124-
// Cache the offset of scrollParent
125-
// TODO: store overflow height/width in a hash instead of separate properties
126-
this.overflowOffset = this.scrollParent.offset();
127-
this.overflowHeight = ( this.scrollParent[0] === this.doc[0] ) ?
171+
// Cache the offset of scrollParent, if required for _handleScrolling
172+
if ( this.scrollParent[0] != this.doc[0] && this.scrollParent[0].tagName != 'HTML') {
173+
this.overflowOffset = this.scrollParent.offset();
174+
}
175+
176+
this.overflow = {};
177+
178+
this.overflow.height = ( this.scrollParent[0] === this.doc[0] ) ?
128179
this.win.height() : this.scrollParent.height();
129-
this.overflowWidth = ( this.scrollParent[0] === this.doc[0] ) ?
180+
181+
this.overflow.width = ( this.scrollParent[0] === this.doc[0] ) ?
130182
this.win.width() : this.scrollParent.width();
131183

132-
// TODO: allow modifying position, just like during drag
184+
this._preparePosition( event );
185+
133186
this._trigger( "start", event, this._uiHash() );
187+
188+
// TODO: should user be able to change position of draggable, if event stopped?
189+
// If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes
190+
if ( event.cancelBubble === true ) {
191+
this.doc.unbind( "." + this.widgetName );
192+
return;
193+
}
194+
195+
this._setCss( event );
134196

135197
this._bind( this.doc, {
136198
mousemove: "_mouseMove",
@@ -139,24 +201,76 @@ $.widget( "ui.draggable", {
139201
},
140202

141203
_mouseMove: function( event ) {
204+
var newLeft, newTop;
205+
206+
this._preparePosition( event );
207+
208+
this._trigger( "drag", event, this._uiHash() );
209+
210+
// TODO: should user be able to change position of draggable, if event stopped?
211+
// If user stops propagation, leave helper there ( if there's one ), disallow any CSS changes
212+
if ( event.cancelBubble === true ) {
213+
this.doc.unbind( "." + this.widgetName );
214+
return;
215+
}
216+
217+
this._setCss( event );
218+
219+
// Scroll the scrollParent, if needed
220+
this._handleScrolling( event );
221+
},
222+
223+
_mouseUp: function( event ) {
224+
225+
this._preparePosition( event );
226+
227+
this._trigger( "stop", event, this._uiHash() );
228+
229+
// TODO: should user be able to change position of draggable, if event stopped?
230+
// If user stops propagation, leave helper there, disallow any CSS changes
231+
if ( event.cancelBubble !== true ) {
232+
233+
this._setCss( event );
234+
235+
if ( this.options.helper ) {
236+
this.dragEl.remove();
237+
}
238+
239+
}
240+
241+
this.doc.unbind( "." + this.widgetName );
242+
},
243+
244+
// Uses event to determine new position of draggable, before any override from callbacks
245+
_preparePosition: function( event ) {
142246
var leftDiff = event.clientX - this.startCoords.left,
143247
topDiff = event.clientY - this.startCoords.top,
144248
newLeft = leftDiff + this.startPosition.left,
145249
newTop = topDiff + this.startPosition.top;
146250

251+
// Save off new values for .css() in various callbacks using this function
147252
this.position = {
148253
left: newLeft,
149254
top: newTop
150255
};
151256

257+
// Save off values to compare user override against automatic coordinates
258+
this.tempPosition = {
259+
left: newLeft,
260+
top: newTop
261+
}
262+
152263
// Refresh offset cache with new positions
153264
this.offset.left = this.startOffset.left + newLeft;
154265
this.offset.top = this.startOffset.top + newTop;
266+
},
155267

156-
this._trigger( "drag", event, this._uiHash() );
268+
// Places draggable where mouse or user from callback indicates
269+
_setCss: function( event ) {
270+
var newLeft, newTop;
157271

158272
// User overriding left/top so shortcut math is no longer valid
159-
if ( newLeft !== this.position.left || newTop !== this.position.top ) {
273+
if ( this.tempPosition.left !== this.position.left || this.tempPosition.top !== this.position.top ) {
160274
// TODO: can we just store the previous offset values
161275
// and not go through .offset()?
162276
// refresh offset using slower functions
@@ -176,34 +290,6 @@ $.widget( "ui.draggable", {
176290
left: newLeft + "px",
177291
top: newTop + "px"
178292
});
179-
180-
// Scroll the scrollParent, if needed
181-
this._handleScrolling( event );
182-
},
183-
184-
_handleScrolling: function( event ) {
185-
var scrollTop = this.doc.scrollTop(),
186-
scrollLeft = this.doc.scrollLeft();
187-
188-
// Handle vertical scrolling
189-
if ( ( ( this.overflowHeight + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) {
190-
this.doc.scrollTop( scrollTop + this.options.scrollSpeed );
191-
}
192-
193-
// Handle horizontal scrolling
194-
if ( ( ( this.overflowWidth + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) {
195-
this.doc.scrollLeft( scrollLeft + this.options.scrollSpeed );
196-
}
197-
},
198-
199-
_mouseUp: function( event ) {
200-
this._trigger( "stop", event, this._uiHash() );
201-
202-
if ( this.options.helper ) {
203-
this.dragEl.remove();
204-
}
205-
206-
this.doc.unbind( "." + this.widgetName );
207293
},
208294

209295
_uiHash: function( event ) {

ui/jquery.ui.widget.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ $.Widget.prototype = {
183183
_createWidget: function( options, element ) {
184184
element = $( element || this.defaultElement || this )[ 0 ];
185185
this.element = $( element );
186+
this.doc = $( this.element[0].ownerDocument );
187+
this.win = $( this.doc[0].defaultView );
188+
this.body = this.doc.body;
186189
this.options = $.widget.extend( {},
187190
this.options,
188191
this._getCreateOptions(),

0 commit comments

Comments
 (0)