jquery.event.drag.custom.js
5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* @license
* jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
* Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
*/
;(function($){ // secure $ jQuery alias
/*******************************************************************************************/
// Created: 2008-06-04 | Updated: 2009-03-24
/*******************************************************************************************/
// Events: drag, dragstart, dragend
/*******************************************************************************************/
// jquery method
$.fn.drag = function( fn1, fn2, fn3 ){
if ( fn2 ) this.bind('dragstart', fn1 ); // 2+ args
if ( fn3 ) this.bind('dragend', fn3 ); // 3 args
return !fn1 ? this.trigger('drag') // 0 args
: this.bind('drag', fn2 ? fn2 : fn1 ); // 1+ args
};
// local refs
var $event = $.event, $special = $event.special,
// special event configuration
drag = $special.drag = {
not: ':input', // don't begin to drag on event.targets that match this selector
distance: 0, // distance dragged before dragstart
which: 1, // mouse button pressed to start drag sequence
dragging: false, // hold the active target element
setup: function( data ){
data = $.extend({
distance: drag.distance,
which: drag.which,
not: drag.not
}, data || {});
data.distance = squared( data.distance ); // xІ + yІ = distanceІ
$event.add( this, "mousedown", handler, data );
if ( this.attachEvent ) this.attachEvent("ondragstart", dontStart ); // prevent image dragging in IE...
},
teardown: function(){
$event.remove( this, "mousedown", handler );
if ( this === drag.dragging ) drag.dragging = drag.proxy = false; // deactivate element
selectable( this, true ); // enable text selection
if ( this.detachEvent ) this.detachEvent("ondragstart", dontStart ); // prevent image dragging in IE...
}
};
// prevent normal event binding...
$special.dragstart = $special.dragend = { setup:function(){}, teardown:function(){} };
// handle drag-releatd DOM events
function handler ( event ){
var elem = this, returned, data = event.data || {};
// mousemove or mouseup
if ( data.elem ){
// update event properties...
elem = event.dragTarget = data.elem; // drag source element
event.dragProxy = drag.proxy || elem; // proxy element or source
event.cursorOffsetX = data.pageX - data.left; // mousedown offset
event.cursorOffsetY = data.pageY - data.top; // mousedown offset
event.offsetX = event.pageX - event.cursorOffsetX; // element offset
event.offsetY = event.pageY - event.cursorOffsetY; // element offset
}
// mousedown, check some initial props to avoid the switch statement
else if ( drag.dragging || ( data.which>0 && event.which!=data.which ) ||
$( event.target ).is( data.not ) ) return;
// handle various events
switch ( event.type ){
// mousedown, left click, event.target is not restricted, init dragging
case 'mousedown':
returned = hijack(event, "beforedragstart", elem);
if (returned === false)
return true;
$.extend( data, $( elem ).offset(), {
elem: elem, target: event.target,
pageX: event.pageX, pageY: event.pageY
}); // store some initial attributes
$event.add( document, "mousemove mouseup", handler, data );
selectable( elem, false ); // disable text selection
drag.dragging = null; // pending state
return false; // prevents text selection in safari
// mousemove, check distance, start dragging
case !drag.dragging && 'mousemove':
if ( squared( event.pageX-data.pageX )
+ squared( event.pageY-data.pageY ) // xІ + yІ = distanceІ
< data.distance ) break; // distance tolerance not reached
event.target = data.target; // force target from "mousedown" event (fix distance issue)
returned = hijack( event, "dragstart", elem ); // trigger "dragstart", return proxy element
if ( returned !== false ){ // "dragstart" not rejected
drag.dragging = elem; // activate element
drag.proxy = event.dragProxy = $( returned || elem )[0]; // set proxy
}
// mousemove, dragging
case 'mousemove':
if ( drag.dragging ){
returned = hijack( event, "drag", elem ); // trigger "drag"
if ( $special.drop ){ // manage drop events
$special.drop.allowed = ( returned !== false ); // prevent drop
$special.drop.handler( event ); // "dropstart", "dropend"
}
if ( returned !== false ) break; // "drag" not rejected, stop
event.type = "mouseup"; // helps "drop" handler behave
}
// mouseup, stop dragging
case 'mouseup':
if (drag.dragging === false) break;
$event.remove( document, "mousemove mouseup", handler ); // remove page events
if ( drag.dragging ){
if ( $special.drop ) $special.drop.handler( event ); // "drop"
hijack( event, "dragend", elem ); // trigger "dragend"
}
selectable( elem, true ); // enable text selection
drag.dragging = drag.proxy = data.elem = false; // deactivate element
break;
}
return true;
};
// set event type to custom value, and handle it
function hijack ( event, type, elem ){
event.type = type; // force the event type
var result = $.event.handle.call( elem, event );
return result===false ? false : result || event.result;
};
// return the value squared
function squared ( value ){ return Math.pow( value, 2 ); };
// suppress default dragstart IE events...
function dontStart(){ return ( drag.dragging === false ); };
// toggles text selection attributes
function selectable ( elem, bool ){
if ( !elem ) return; // maybe element was removed ?
elem.unselectable = bool ? "off" : "on"; // IE
elem.onselectstart = function(){ return bool; }; // IE
//if ( document.selection && document.selection.empty ) document.selection.empty(); // IE
if ( elem.style ) elem.style.MozUserSelect = bool ? "" : "none"; // FF
};
/*******************************************************************************************/
})( jQuery ); // confine scope