Subversion Repositories DevTools

Rev

Rev 13 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
13 rsolanki 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
		}
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
}
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
	 *   - 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
 
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
		})
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
		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
		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
 
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
 
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
		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
					: coordinate
233
		}
234
	}
235
}