1 rizwank 1.1 /* Copyright (c) 2005 Tim Taylor Consulting (see LICENSE.txt) */
2
3 ToolMan._dragFactory = {
4 createSimpleGroup : function(element, handle) {
5 handle = handle ? handle : element
6 var group = this.createGroup(element)
7 group.setHandle(handle)
8 group.transparentDrag()
9 group.onTopWhileDragging()
10 return group
11 },
12
13 createGroup : function(element) {
14 var group = new _ToolManDragGroup(this, element)
15
16 var position = ToolMan.css().readStyle(element, 'position')
17 if (position == 'static') {
18 element.style["position"] = 'relative'
19 } else if (position == 'absolute') {
20 /* for Safari 1.2 */
21 ToolMan.coordinates().topLeftOffset(element).reposition(element)
22 rizwank 1.1 }
23
24 // TODO: only if ToolMan.isDebugging()
25 group.register('draginit', this._showDragEventStatus)
26 group.register('dragmove', this._showDragEventStatus)
27 group.register('dragend', this._showDragEventStatus)
28
29 return group
30 },
31
32 _showDragEventStatus : function(dragEvent) {
33 window.status = dragEvent.toString()
34 },
35
36 constraints : function() {
37 return this._constraintFactory
38 },
39
40 _createEvent : function(type, event, group) {
41 return new _ToolManDragEvent(type, event, group)
42 }
43 rizwank 1.1 }
44
45 function _ToolManDragGroup(factory, element) {
46 this.factory = factory
47 this.element = element
48 this._handle = null
49 this._thresholdDistance = 0
50 this._transforms = new Array()
51 // TODO: refactor into a helper object, move into events.js
52 this._listeners = new Array()
53 this._listeners['draginit'] = new Array()
54 this._listeners['dragstart'] = new Array()
55 this._listeners['dragmove'] = new Array()
56 this._listeners['dragend'] = new Array()
57 }
58
59 _ToolManDragGroup.prototype = {
60 /*
61 * TODO:
62 * - unregister(type, func)
63 * - move custom event listener stuff into Event library
64 rizwank 1.1 * - keyboard nudging of "selected" group
65 */
66
67 setHandle : function(handle) {
68 var events = ToolMan.events()
69
70 handle.toolManDragGroup = this
71 events.register(handle, 'mousedown', this._dragInit)
72 handle.onmousedown = function() { return false }
73
74 if (this.element != handle)
75 events.unregister(this.element, 'mousedown', this._dragInit)
76 },
77
78 register : function(type, func) {
79 this._listeners[type].push(func)
80 },
81
82 addTransform : function(transformFunc) {
83 this._transforms.push(transformFunc)
84 },
85 rizwank 1.1
86 verticalOnly : function() {
87 this.addTransform(this.factory.constraints().vertical())
88 },
89
90 horizontalOnly : function() {
91 this.addTransform(this.factory.constraints().horizontal())
92 },
93
94 setThreshold : function(thresholdDistance) {
95 this._thresholdDistance = thresholdDistance
96 },
97
98 transparentDrag : function(opacity) {
99 var opacity = typeof(opacity) != "undefined" ? opacity : 0.75;
100 var originalOpacity = ToolMan.css().readStyle(this.element, "opacity")
101
102 this.register('dragstart', function(dragEvent) {
103 var element = dragEvent.group.element
104 element.style.opacity = opacity
105 element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')'
106 rizwank 1.1 })
107 this.register('dragend', function(dragEvent) {
108 var element = dragEvent.group.element
109 element.style.opacity = originalOpacity
110 element.style.filter = 'alpha(opacity=100)'
111 })
112 },
113
114 onTopWhileDragging : function(zIndex) {
115 var zIndex = typeof(zIndex) != "undefined" ? zIndex : 100000;
116 var originalZIndex = ToolMan.css().readStyle(this.element, "z-index")
117
118 this.register('dragstart', function(dragEvent) {
119 dragEvent.group.element.style.zIndex = zIndex
120 })
121 this.register('dragend', function(dragEvent) {
122 dragEvent.group.element.style.zIndex = originalZIndex
123 })
124 },
125
126 _dragInit : function(event) {
127 rizwank 1.1 event = ToolMan.events().fix(event)
128 var group = document.toolManDragGroup = this.toolManDragGroup
129 var dragEvent = group.factory._createEvent('draginit', event, group)
130
131 group._isThresholdExceeded = false
132 group._initialMouseOffset = dragEvent.mouseOffset
133 group._grabOffset = dragEvent.mouseOffset.minus(dragEvent.topLeftOffset)
134 ToolMan.events().register(document, 'mousemove', group._drag)
135 document.onmousemove = function() { return false }
136 ToolMan.events().register(document, 'mouseup', group._dragEnd)
137
138 group._notifyListeners(dragEvent)
139 },
140
141 _drag : function(event) {
142 event = ToolMan.events().fix(event)
143 var coordinates = ToolMan.coordinates()
144 var group = this.toolManDragGroup
145 if (!group) return
146 var dragEvent = group.factory._createEvent('dragmove', event, group)
147
148 rizwank 1.1 var newTopLeftOffset = dragEvent.mouseOffset.minus(group._grabOffset)
149
150 // TODO: replace with DragThreshold object
151 if (!group._isThresholdExceeded) {
152 var distance =
153 dragEvent.mouseOffset.distance(group._initialMouseOffset)
154 if (distance < group._thresholdDistance) return
155 group._isThresholdExceeded = true
156 group._notifyListeners(
157 group.factory._createEvent('dragstart', event, group))
158 }
159
160 for (i in group._transforms) {
161 var transform = group._transforms[i]
162 newTopLeftOffset = transform(newTopLeftOffset, dragEvent)
163 }
164
165 var dragDelta = newTopLeftOffset.minus(dragEvent.topLeftOffset)
166 var newTopLeftPosition = dragEvent.topLeftPosition.plus(dragDelta)
167 newTopLeftPosition.reposition(group.element)
168 dragEvent.transformedMouseOffset = newTopLeftOffset.plus(group._grabOffset)
169 rizwank 1.1
170 group._notifyListeners(dragEvent)
171
172 var errorDelta = newTopLeftOffset.minus(coordinates.topLeftOffset(group.element))
173 if (errorDelta.x != 0 || errorDelta.y != 0) {
174 coordinates.topLeftPosition(group.element).plus(errorDelta).reposition(group.element)
175 }
176 },
177
178 _dragEnd : function(event) {
179 event = ToolMan.events().fix(event)
180 var group = this.toolManDragGroup
181 var dragEvent = group.factory._createEvent('dragend', event, group)
182
183 group._notifyListeners(dragEvent)
184
185 this.toolManDragGroup = null
186 ToolMan.events().unregister(document, 'mousemove', group._drag)
187 document.onmousemove = null
188 ToolMan.events().unregister(document, 'mouseup', group._dragEnd)
189 },
190 rizwank 1.1
191 _notifyListeners : function(dragEvent) {
192 var listeners = this._listeners[dragEvent.type]
193 for (i in listeners) {
194 listeners[i](dragEvent)
195 }
196 }
197 }
198
199 function _ToolManDragEvent(type, event, group) {
200 this.type = type
201 this.group = group
202 this.mousePosition = ToolMan.coordinates().mousePosition(event)
203 this.mouseOffset = ToolMan.coordinates().mouseOffset(event)
204 this.transformedMouseOffset = this.mouseOffset
205 this.topLeftPosition = ToolMan.coordinates().topLeftPosition(group.element)
206 this.topLeftOffset = ToolMan.coordinates().topLeftOffset(group.element)
207 }
208
209 _ToolManDragEvent.prototype = {
210 toString : function() {
211 rizwank 1.1 return "mouse: " + this.mousePosition + this.mouseOffset + " " +
212 "xmouse: " + this.transformedMouseOffset + " " +
213 "left,top: " + this.topLeftPosition + this.topLeftOffset
214 }
215 }
216
217 ToolMan._dragFactory._constraintFactory = {
218 vertical : function() {
219 return function(coordinate, dragEvent) {
220 var x = dragEvent.topLeftOffset.x
221 return coordinate.x != x
222 ? coordinate.factory.create(x, coordinate.y)
223 : coordinate
224 }
225 },
226
227 horizontal : function() {
228 return function(coordinate, dragEvent) {
229 var y = dragEvent.topLeftOffset.y
230 return coordinate.y != y
231 ? coordinate.factory.create(coordinate.x, y)
232 rizwank 1.1 : coordinate
233 }
234 }
235 }
|