Skip to content

Commit 6ea6c47

Browse files
committed
Merge pull request #2 from scottgonzalez/interactions
Draggable: Cleanup.
2 parents c8e1370 + ee094cc commit 6ea6c47

File tree

1 file changed

+78
-161
lines changed

1 file changed

+78
-161
lines changed

ui/jquery.ui.draggable.js

+78-161
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
2-
* jQuery UI Draggable 2.0.0
2+
* jQuery UI Draggable @VERSION
33
*
44
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
55
* Dual licensed under the MIT or GPL Version 2 licenses.
66
* http://jquery.org/license
77
*
8-
* http://docs.jquery.com/UI/Draggables
8+
* http://docs.jquery.com/UI/Draggable
99
*
1010
* Depends:
1111
* jquery.ui.core.js
@@ -14,90 +14,59 @@
1414
(function( $, undefined ) {
1515

1616
$.widget( "ui.draggable", {
17-
17+
version: "@VERSION",
1818
widgetEventPrefix: "drag",
1919

2020
options: {
21-
22-
scrollSpeed: 20,
23-
scrollSensitivity:20,
24-
helper: false
25-
21+
helper: false,
22+
scrollSensitivity: 20,
23+
scrollSpeed: 20
2624
},
2725

28-
// TODO: actually remove data
29-
destroy: function() {
30-
return this;
31-
},
26+
// dragEl: element being dragged (original or helper)
27+
// position: CSS position of dragEl
28+
// offset: offset of dragEl
29+
// startCoords: clientX/Y of the mousedown (offset of pointer)
30+
// startPosition: CSS position prior to drag start
31+
// startOffset: offset prior to drag start
32+
// overflowOffset: offset of scroll parent
33+
// overflowHeight: height of scroll parent
34+
// overflowWidth: width of scroll parent
3235

3336
_create: function() {
34-
35-
// Either initialized element or the helper
36-
this.dragEl = false,
37-
38-
this.position = {},
39-
this.offset = {},
40-
41-
// Start X/Y coords of mouse before drag
42-
this.startCoords = {},
43-
44-
// Start position of element before drag
45-
this.startPosition = {},
46-
47-
// Start offset of element before drag
48-
this.startOffset = {},
37+
// TODO: add these to the base widget
38+
this.doc = $( this.element[0].ownerDocument );
39+
this.win = $( this.doc[0].defaultView );
4940

5041
this.scrollParent = this.element.scrollParent();
5142

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-
61-
// Static position elements can"t be moved with top/left
43+
// Static position elements can't be moved with top/left
6244
if ( this.element.css( "position" ) === "static" ) {
6345
this.element.css( "position", "relative" );
6446
}
65-
66-
// Using proxy to avoid anon functions using self to pass "this" along
67-
this.element.bind( "mousedown." + this.widgetName, $.proxy( this._mouseDown, this ) );
68-
69-
},
7047

71-
_usingHelper : function() {
72-
return ( this.options.helper === true || typeof this.options.helper === 'function' );
48+
// TODO: use _bind()
49+
this.element.bind( "mousedown." + this.widgetName, $.proxy( this, "_mouseDown" ) );
7350
},
7451

75-
_setPosition: function() {
76-
52+
// TODO: why is relative handled differently than fixed/absolute?
53+
_getPosition: function() {
7754
var left, top, position,
78-
scrollTop = this.scrollParent.scrollTop(),
79-
scrollLeft = this.scrollParent.scrollLeft();
80-
81-
// Helper is appended to body so offset of element is all that's needed
82-
if ( this._usingHelper() ) {
83-
return this.element.offset();
84-
}
55+
scrollTop = this.scrollParent.scrollTop(),
56+
scrollLeft = this.scrollParent.scrollLeft();
8557

8658
// If fixed or absolute
8759
if ( this.cssPosition !== "relative" ) {
88-
8960
position = this.dragEl.position();
9061

9162
// Take into account scrollbar
92-
position.top = position.top - scrollTop;
93-
position.left = position.left - scrollLeft
63+
position.top -= scrollTop;
64+
position.left -= scrollLeft
9465

9566
return position;
96-
9767
}
9868

99-
/** When using relative, css values are checked **/
100-
69+
// When using relative, css values are checked
10170
left = this.dragEl.css( "left" );
10271
top = this.dragEl.css( "top" );
10372

@@ -106,64 +75,42 @@ $.widget( "ui.draggable", {
10675
top = ( top === "auto" ) ? 0: parseInt( top, 10 );
10776

10877
return {
109-
11078
left: left - scrollLeft,
11179
top: top - scrollTop
112-
11380
};
114-
11581
},
11682

11783
_mouseDown: function( event ) {
118-
119-
// Stop browser from highlighting, among other things
120-
event.preventDefault();
84+
// Prevent text selection, among other things
85+
event.preventDefault();
12186

12287
// The actual dragging element, should always be a jQuery object
12388
this.dragEl = this.element;
124-
12589
this.cssPosition = this.dragEl.css( "position" );
12690

127-
// Helper required, so clone, hide, and set reference
128-
if ( this._usingHelper() ) {
129-
130-
// If getting a cloned helper
91+
// Helper required
92+
if ( this.options.helper ) {
93+
// clone
13194
if ( this.options.helper === true ) {
132-
133-
this.dragEl = this.element.clone();
134-
13595
// If source element has an ID, change ID of helper to avoid overlap
96+
this.dragEl = this.element.clone();
13697
if ( this.element.attr( "id" ) ) {
137-
13898
this.dragEl.attr( "id", this.element.attr( "id" ) + "-" + this.widgetName );
139-
14099
}
141-
142100
} else {
143-
144-
this.dragEl = this.options.helper();
145-
146-
// If function was passed, it should return a DOMElement
147-
if ( typeof this.dragEl.nodeType !== 'number' ) {
148-
throw "Helper function must return a DOMElement";
149-
}
150-
151-
this.dragEl = $( this.dragEl );
152-
101+
// TODO: figure out the signature for this; see #4957
102+
this.dragEl = $( this.options.helper() );
153103
}
154104

155-
// Automatically make helper absolute
156105
this.dragEl
157-
.css({
158-
position: "absolute"
159-
});
160-
161-
$( "body" ).append( this.dragEl );
162-
106+
// TODO: should we move this to the stylesheet and use a class?
107+
.css( "position", "absolute" )
108+
.appendTo( this.doc[0].body )
109+
.offset( this.element.offset() );
163110
}
164111

165112
// Cache starting absolute and relative positions
166-
this.startPosition = this._setPosition();
113+
this.startPosition = this._getPosition();
167114
this.startOffset = this.dragEl.offset();
168115

169116
// Cache current position and offset
@@ -176,38 +123,28 @@ $.widget( "ui.draggable", {
176123
};
177124

178125
// Cache the offset of scrollParent
126+
// TODO: store overflow height/width in a hash instead of separate properties
179127
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-
183-
this._trigger( "start", event );
184-
185-
$(document).bind( "mousemove." + this.widgetName, $.proxy( this._mouseMove, this ) )
186-
.bind( "mouseup." + this.widgetName, $.proxy( this._mouseUp, this ) );
187-
188-
189-
// Set the helper up by actual element
190-
if ( this._usingHelper() ) {
191-
192-
// get the absolute position of element so that helper will know where to go
193-
elOffset = this.element.offset();
194-
195-
this.dragEl.css({
196-
display: "block",
197-
top: elOffset.top + "px",
198-
left: elOffset.left + "px"
199-
});
200-
201-
}
202-
128+
this.overflowHeight = ( this.scrollParent[0] === this.doc[0] ) ?
129+
this.win.height() : this.scrollParent.height();
130+
this.overflowWidth = ( this.scrollParent[0] === this.doc[0] ) ?
131+
this.win.width() : this.scrollParent.width();
132+
133+
// TODO: allow modifying position, just like during drag
134+
this._trigger( "start", event, this._uiHash() );
135+
136+
// TODO: use ._bind()
137+
// TODO: rename _bind() to _on(); add _off()
138+
this.doc
139+
.bind( "mousemove." + this.widgetName, $.proxy( this, "_mouseMove" ) )
140+
.bind( "mouseup." + this.widgetName, $.proxy( this, "_mouseUp" ) );
203141
},
204142

205143
_mouseMove: function( event ) {
206-
207144
var leftDiff = event.clientX - this.startCoords.left,
208-
topDiff = event.clientY - this.startCoords.top,
209-
newLeft = leftDiff + this.startPosition.left,
210-
newTop = topDiff + this.startPosition.top;
145+
topDiff = event.clientY - this.startCoords.top,
146+
newLeft = leftDiff + this.startPosition.left,
147+
newTop = topDiff + this.startPosition.top;
211148

212149
this.position = {
213150
left: newLeft,
@@ -218,87 +155,67 @@ $.widget( "ui.draggable", {
218155
this.offset.left = this.startOffset.left + newLeft;
219156
this.offset.top = this.startOffset.top + newTop;
220157

221-
this._trigger( "drag", event );
158+
this._trigger( "drag", event, this._uiHash() );
222159

223160
// User overriding left/top so shortcut math is no longer valid
224161
if ( newLeft !== this.position.left || newTop !== this.position.top ) {
225-
162+
// TODO: can we just store the previous offset values
163+
// and not go through .offset()?
226164
// refresh offset using slower functions
227165
this.offset = this.dragEl.offset();
228-
229166
}
230-
167+
231168
newLeft = this.position.left;
232169
newTop = this.position.top;
233-
234-
if ( this.cssPosition !== 'fixed' ) {
235-
170+
171+
// TODO: does this work with nested scrollable parents?
172+
if ( this.cssPosition !== "fixed" ) {
236173
newLeft = newLeft + this.scrollParent.scrollLeft();
237174
newTop = newTop + this.scrollParent.scrollTop();
238-
239175
}
240176

241177
this.dragEl.css({
242-
243178
left: newLeft + "px",
244179
top: newTop + "px"
245-
246180
});
247-
181+
248182
// Scroll the scrollParent, if needed
249183
this._handleScrolling( event );
250-
251184
},
252185

253186
_handleScrolling: function( event ) {
254-
255-
var doc = $(document),
256-
scrollTop = doc.scrollTop(),
257-
scrollLeft = doc.scrollLeft();
187+
var scrollTop = this.doc.scrollTop(),
188+
scrollLeft = this.doc.scrollLeft();
258189

259190
// Handle vertical scrolling
260191
if ( ( ( this.overflowHeight + scrollTop ) - event.pageY ) < this.options.scrollSensitivity ) {
261-
doc.scrollTop( scrollTop + this.options.scrollSpeed );
192+
this.doc.scrollTop( scrollTop + this.options.scrollSpeed );
262193
}
263-
194+
264195
// Handle horizontal scrolling
265196
if ( ( ( this.overflowWidth + scrollLeft ) - event.pageX ) < this.options.scrollSensitivity ) {
266-
doc.scrollLeft( scrollLeft + this.options.scrollSpeed );
197+
this.doc.scrollLeft( scrollLeft + this.options.scrollSpeed );
267198
}
268-
269199
},
270200

271201
_mouseUp: function( event ) {
202+
this._trigger( "stop", event, this._uiHash() );
272203

273-
var doc = $(document);
274-
275-
this._trigger( "stop", event );
276-
277-
this.startCoords = {};
278-
279-
if ( this._usingHelper() ) {
204+
if ( this.options.helper ) {
280205
this.dragEl.remove();
281206
}
282207

283-
doc.unbind( "mousemove." + this.widgetName );
284-
doc.unbind( "mouseup." + this.widgetName );
285-
208+
this.doc
209+
.unbind( "mousemove." + this.widgetName )
210+
.unbind( "mouseup." + this.widgetName );
286211
},
287212

288-
_uiHash: function(event) {
289-
213+
_uiHash: function( event ) {
290214
return {
291215
position: this.position,
292216
offset: this.offset
293217
};
294-
295218
}
296-
297-
});
298-
299-
$.extend($.ui.draggable, {
300-
version: "2.0.0"
301219
});
302220

303-
304-
})(jQuery);
221+
})( jQuery );

0 commit comments

Comments
 (0)