@@ -24,20 +24,16 @@ $.widget( "ui.draggable", {
24
24
} ,
25
25
26
26
// dragEl: element being dragged (original or helper)
27
- // position: CSS position of dragEl
27
+ // position: final CSS position of dragEl
28
28
// offset: offset of dragEl
29
29
// startCoords: clientX/Y of the mousedown (offset of pointer)
30
30
// startPosition: CSS position prior to drag start
31
31
// startOffset: offset prior to drag start
32
+ // tempPosition: overridable CSS position of dragEl
32
33
// 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
35
35
36
36
_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
-
41
37
this . scrollParent = this . element . scrollParent ( ) ;
42
38
43
39
// Static position elements can't be moved with top/left
@@ -79,13 +75,62 @@ $.widget( "ui.draggable", {
79
75
} ;
80
76
} ,
81
77
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
+
82
126
_mouseDown : function ( event ) {
127
+ var newLeft , newTop ;
128
+
83
129
// Prevent text selection, among other things
84
130
event . preventDefault ( ) ;
85
131
86
132
// The actual dragging element, should always be a jQuery object
87
133
this . dragEl = this . element ;
88
- this . cssPosition = this . dragEl . css ( "position" ) ;
89
134
90
135
// Helper required
91
136
if ( this . options . helper ) {
@@ -107,6 +152,8 @@ $.widget( "ui.draggable", {
107
152
. appendTo ( this . doc [ 0 ] . body )
108
153
. offset ( this . element . offset ( ) ) ;
109
154
}
155
+
156
+ this . cssPosition = this . dragEl . css ( "position" ) ;
110
157
111
158
// Cache starting absolute and relative positions
112
159
this . startPosition = this . _getPosition ( ) ;
@@ -121,16 +168,31 @@ $.widget( "ui.draggable", {
121
168
top : event . clientY
122
169
} ;
123
170
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 ] ) ?
128
179
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 ] ) ?
130
182
this . win . width ( ) : this . scrollParent . width ( ) ;
131
183
132
- // TODO: allow modifying position, just like during drag
184
+ this . _preparePosition ( event ) ;
185
+
133
186
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 ) ;
134
196
135
197
this . _bind ( this . doc , {
136
198
mousemove : "_mouseMove" ,
@@ -139,24 +201,76 @@ $.widget( "ui.draggable", {
139
201
} ,
140
202
141
203
_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 ) {
142
246
var leftDiff = event . clientX - this . startCoords . left ,
143
247
topDiff = event . clientY - this . startCoords . top ,
144
248
newLeft = leftDiff + this . startPosition . left ,
145
249
newTop = topDiff + this . startPosition . top ;
146
250
251
+ // Save off new values for .css() in various callbacks using this function
147
252
this . position = {
148
253
left : newLeft ,
149
254
top : newTop
150
255
} ;
151
256
257
+ // Save off values to compare user override against automatic coordinates
258
+ this . tempPosition = {
259
+ left : newLeft ,
260
+ top : newTop
261
+ }
262
+
152
263
// Refresh offset cache with new positions
153
264
this . offset . left = this . startOffset . left + newLeft ;
154
265
this . offset . top = this . startOffset . top + newTop ;
266
+ } ,
155
267
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 ;
157
271
158
272
// 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 ) {
160
274
// TODO: can we just store the previous offset values
161
275
// and not go through .offset()?
162
276
// refresh offset using slower functions
@@ -176,34 +290,6 @@ $.widget( "ui.draggable", {
176
290
left : newLeft + "px" ,
177
291
top : newTop + "px"
178
292
} ) ;
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 ) ;
207
293
} ,
208
294
209
295
_uiHash : function ( event ) {
0 commit comments