forked from msnodeve/rlottie.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdragresize_commented.js
More file actions
352 lines (294 loc) · 10.5 KB
/
dragresize_commented.js
File metadata and controls
352 lines (294 loc) · 10.5 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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/*
DragResize v1.0
(c) 2005-2006 Angus Turnbull, TwinHelix Designs http://www.twinhelix.com
Licensed under the CC-GNU LGPL, version 2.1 or later:
http://creativecommons.org/licenses/LGPL/2.1/
This is distributed WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
// Common API code.
if (typeof addEvent != 'function')
{
var addEvent = function(o, t, f, l)
{
var d = 'addEventListener', n = 'on' + t, rO = o, rT = t, rF = f, rL = l;
if (o[d] && !l) return o[d](t, f, false);
if (!o._evts) o._evts = {};
if (!o._evts[t])
{
o._evts[t] = o[n] ? { b: o[n] } : {};
o[n] = new Function('e',
'var r = true, o = this, a = o._evts["' + t + '"], i; for (i in a) {' +
'o._f = a[i]; r = o._f(e||window.event) != false && r; o._f = null;' +
'} return r');
if (t != 'unload') addEvent(window, 'unload', function() {
removeEvent(rO, rT, rF, rL);
});
}
if (!f._i) f._i = addEvent._i++;
o._evts[t][f._i] = f;
};
addEvent._i = 1;
var removeEvent = function(o, t, f, l)
{
var d = 'removeEventListener';
if (o[d] && !l) return o[d](t, f, false);
if (o._evts && o._evts[t] && f._i) delete o._evts[t][f._i];
};
}
function cancelEvent(e, c)
{
e.returnValue = false;
if (e.preventDefault) e.preventDefault();
if (c)
{
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}
};
// *** DRAG/RESIZE CODE ***
function DragResize(myName, config)
{
var props = {
myName: myName, // Name of the object.
enabled: true, // Global toggle of drag/resize.
handles: ['tl', 'tm', 'tr',
'ml', 'mr', 'bl', 'bm', 'br'], // Array of drag handles: top/mid/bot/right.
isElement: null, // Function ref to test for an element.
isHandle: null, // Function ref to test for move handle.
element: null, // The currently selected element.
handle: null, // Active handle reference of the element.
minWidth: 10, minHeight: 10, // Minimum pixel size of elements.
minLeft: 0, maxLeft: 9999, // Bounding box area, in pixels.
minTop: 0, maxTop: 9999,
zIndex: 1, // The highest Z-Index yet allocated.
mouseX: 0, mouseY: 0, // Current mouse position, recorded live.
lastMouseX: 0, lastMouseY: 0, // Last processed mouse positions.
mOffX: 0, mOffY: 0, // A known offset between position & mouse.
elmX: 0, elmY: 0, // Element position.
elmW: 0, elmH: 0, // Element size.
allowBlur: true, // Whether to allow automatic blur onclick.
ondragfocus: null, // Event handler functions.
ondragstart: null,
ondragmove: null,
ondragend: null,
ondragblur: null
};
for (var p in props)
this[p] = (typeof config[p] == 'undefined') ? props[p] : config[p];
};
DragResize.prototype.apply = function(node)
{
// Adds object event handlers to the specified DOM node.
var obj = this;
addEvent(node, 'mousedown', function(e) { obj.mouseDown(e) } );
addEvent(node, 'mousemove', function(e) { obj.mouseMove(e) } );
addEvent(node, 'mouseup', function(e) { obj.mouseUp(e) } );
};
DragResize.prototype.select = function(newElement) { with (this)
{
// Selects an element for dragging.
if (!document.getElementById || !enabled) return;
// Activate and record our new dragging element.
if (newElement && (newElement != element) && enabled)
{
element = newElement;
// Elevate it and give it resize handles.
element.style.zIndex = ++zIndex;
if (this.resizeHandleSet) this.resizeHandleSet(element, true);
// Record element attributes for mouseMove().
elmX = parseInt(element.style.left);
elmY = parseInt(element.style.top);
elmW = element.offsetWidth;
elmH = element.offsetHeight;
if (ondragfocus) this.ondragfocus();
}
}};
DragResize.prototype.deselect = function(delHandles) { with (this)
{
// Immediately stops dragging an element. If 'delHandles' is true, this
// remove the handles from the element and clears the element flag,
// completely resetting the .
if (!document.getElementById || !enabled) return;
if (delHandles)
{
if (ondragblur) this.ondragblur();
if (this.resizeHandleSet) this.resizeHandleSet(element, false);
element = null;
}
handle = null;
mOffX = 0;
mOffY = 0;
}};
DragResize.prototype.mouseDown = function(e) { with (this)
{
// Suitable elements are selected for drag/resize on mousedown.
// We also initialise the resize boxes, and drag parameters like mouse position etc.
if (!document.getElementById || !enabled) return true;
var elm = e.target || e.srcElement,
newElement = null,
newHandle = null,
hRE = new RegExp(myName + '-([trmbl]{2})', '');
while (elm)
{
// Loop up the DOM looking for matching elements. Remember one if found.
if (elm.className)
{
if (!newHandle && (hRE.test(elm.className) || isHandle(elm))) newHandle = elm;
if (isElement(elm)) { newElement = elm; break }
}
elm = elm.parentNode;
}
// If this isn't on the last dragged element, call deselect(),
// which will hide its handles and clear element.
if (element && (element != newElement) && allowBlur) deselect(true);
// If we have a new matching element, call select().
if (newElement && (!element || (newElement == element)))
{
// Stop mouse selections if we're dragging a handle.
if (newHandle) cancelEvent(e);
select(newElement, newHandle);
handle = newHandle;
if (handle && ondragstart) this.ondragstart(hRE.test(handle.className));
}
}};
DragResize.prototype.mouseMove = function(e) { with (this)
{
// This continually offsets the dragged element by the difference between the
// last recorded mouse position (mouseX/Y) and the current mouse position.
if (!document.getElementById || !enabled) return true;
// We always record the current mouse position.
mouseX = e.pageX || e.clientX + document.documentElement.scrollLeft;
mouseY = e.pageY || e.clientY + document.documentElement.scrollTop;
// Record the relative mouse movement, in case we're dragging.
// Add any previously stored & ignored offset to the calculations.
var diffX = mouseX - lastMouseX + mOffX;
var diffY = mouseY - lastMouseY + mOffY;
mOffX = mOffY = 0;
// Update last processed mouse positions.
lastMouseX = mouseX;
lastMouseY = mouseY;
// That's all we do if we're not dragging anything.
if (!handle) return true;
// If included in the script, run the resize handle drag routine.
// Let it create an object representing the drag offsets.
var isResize = false;
if (this.resizeHandleDrag && this.resizeHandleDrag(diffX, diffY))
{
isResize = true;
}
else
{
// If the resize drag handler isn't set or returns fase (to indicate the drag was
// not on a resize handle), we must be dragging the whole element, so move that.
// Bounds check left-right...
var dX = diffX, dY = diffY;
if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
else if (elmX + elmW + dX > maxLeft) mOffX = (dX - (diffX = maxLeft - elmX - elmW));
// ...and up-down.
if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
else if (elmY + elmH + dY > maxTop) mOffY = (dY - (diffY = maxTop - elmY - elmH));
elmX += diffX;
elmY += diffY;
}
// Assign new info back to the element, with minimum dimensions.
with (element.style)
{
left = elmX + 'px';
width = elmW + 'px';
top = elmY + 'px';
height = elmH + 'px';
}
// Evil, dirty, hackish Opera select-as-you-drag fix.
if (window.opera && document.documentElement)
{
var oDF = document.getElementById('op-drag-fix');
if (!oDF)
{
var oDF = document.createElement('input');
oDF.id = 'op-drag-fix';
oDF.style.display = 'none';
document.body.appendChild(oDF);
}
oDF.focus();
}
if (ondragmove) this.ondragmove(isResize);
// Stop a normal drag event.
cancelEvent(e);
}};
DragResize.prototype.mouseUp = function(e) { with (this)
{
// On mouseup, stop dragging, but don't reset handler visibility.
if (!document.getElementById || !enabled) return;
var hRE = new RegExp(myName + '-([trmbl]{2})', '');
if (handle && ondragend) this.ondragend(hRE.test(handle.className));
deselect(false);
}};
/* Resize Code -- can be deleted if you're not using it. */
DragResize.prototype.resizeHandleSet = function(elm, show) { with (this)
{
// Either creates, shows or hides the resize handles within an element.
// If we're showing them, and no handles have been created, create 4 new ones.
if (!elm._handle_tr)
{
for (var h = 0; h < handles.length; h++)
{
// Create 4 news divs, assign each a generic + specific class.
var hDiv = document.createElement('div');
hDiv.className = myName + ' ' + myName + '-' + handles[h];
elm['_handle_' + handles[h]] = elm.appendChild(hDiv);
}
}
// We now have handles. Find them all and show/hide.
for (var h = 0; h < handles.length; h++)
{
elm['_handle_' + handles[h]].style.visibility = show ? 'inherit' : 'hidden';
}
}};
DragResize.prototype.resizeHandleDrag = function(diffX, diffY) { with (this)
{
// Passed the mouse movement amounts. This function checks to see whether the
// drag is from a resize handle created above; if so, it changes the stored
// elm* dimensions and mOffX/Y.
var hClass = handle && handle.className &&
handle.className.match(new RegExp(myName + '-([tmblr]{2})')) ? RegExp.$1 : '';
// If the hClass is one of the resize handles, resize one or two dimensions.
// Bounds checking is the hard bit -- basically for each edge, check that the
// element doesn't go under minimum size, and doesn't go beyond its boundary.
var dY = diffY, dX = diffX, processed = false;
if (hClass.indexOf('t') >= 0)
{
rs = 1;
if (elmH - dY < minHeight) mOffY = (dY - (diffY = elmH - minHeight));
else if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
elmY += diffY;
elmH -= diffY;
processed = true;
}
if (hClass.indexOf('b') >= 0)
{
rs = 1;
if (elmH + dY < minHeight) mOffY = (dY - (diffY = minHeight - elmH));
else if (elmY + elmH + dY > maxTop) mOffY = (dY - (diffY = maxTop - elmY - elmH));
elmH += diffY;
processed = true;
}
if (hClass.indexOf('l') >= 0)
{
rs = 1;
if (elmW - dX < minWidth) mOffX = (dX - (diffX = elmW - minWidth));
else if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
elmX += diffX;
elmW -= diffX;
processed = true;
}
if (hClass.indexOf('r') >= 0)
{
rs = 1;
if (elmW + dX < minWidth) mOffX = (dX - (diffX = minWidth - elmW));
else if (elmX + elmW + dX > maxLeft) mOffX = (dX - (diffX = maxLeft - elmX - elmW));
elmW += diffX;
processed = true;
}
return processed;
}};