author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
commit | ef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (unidiff) | |
tree | c403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/beta/js/MochiKit/DragAndDrop.js | |
parent | 597ecfbc0249d83e1b856cbd558340c01237a360 (diff) | |
download | clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2 |
First version of the newly restructured repository
Diffstat (limited to 'frontend/beta/js/MochiKit/DragAndDrop.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/MochiKit/DragAndDrop.js | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/frontend/beta/js/MochiKit/DragAndDrop.js b/frontend/beta/js/MochiKit/DragAndDrop.js new file mode 100644 index 0000000..c471ffe --- a/dev/null +++ b/frontend/beta/js/MochiKit/DragAndDrop.js | |||
@@ -0,0 +1,824 @@ | |||
1 | /*** | ||
2 | MochiKit.DragAndDrop 1.4 | ||
3 | |||
4 | See <http://mochikit.com/> for documentation, downloads, license, etc. | ||
5 | |||
6 | Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) | ||
7 | Mochi-ized By Thomas Herve (_firstname_@nimail.org) | ||
8 | |||
9 | ***/ | ||
10 | |||
11 | if (typeof(dojo) != 'undefined') { | ||
12 | dojo.provide('MochiKit.DragAndDrop'); | ||
13 | dojo.require('MochiKit.Base'); | ||
14 | dojo.require('MochiKit.DOM'); | ||
15 | dojo.require('MochiKit.Iter'); | ||
16 | dojo.require('MochiKit.Visual'); | ||
17 | dojo.require('MochiKit.Signal'); | ||
18 | } | ||
19 | |||
20 | if (typeof(JSAN) != 'undefined') { | ||
21 | JSAN.use("MochiKit.Base", []); | ||
22 | JSAN.use("MochiKit.DOM", []); | ||
23 | JSAN.use("MochiKit.Visual", []); | ||
24 | JSAN.use("MochiKit.Iter", []); | ||
25 | JSAN.use("MochiKit.Signal", []); | ||
26 | } | ||
27 | |||
28 | try { | ||
29 | if (typeof(MochiKit.Base) == 'undefined' || | ||
30 | typeof(MochiKit.DOM) == 'undefined' || | ||
31 | typeof(MochiKit.Visual) == 'undefined' || | ||
32 | typeof(MochiKit.Signal) == 'undefined' || | ||
33 | typeof(MochiKit.Iter) == 'undefined') { | ||
34 | throw ""; | ||
35 | } | ||
36 | } catch (e) { | ||
37 | throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!"; | ||
38 | } | ||
39 | |||
40 | if (typeof(MochiKit.DragAndDrop) == 'undefined') { | ||
41 | MochiKit.DragAndDrop = {}; | ||
42 | } | ||
43 | |||
44 | MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop'; | ||
45 | MochiKit.DragAndDrop.VERSION = '1.4'; | ||
46 | |||
47 | MochiKit.DragAndDrop.__repr__ = function () { | ||
48 | return '[' + this.NAME + ' ' + this.VERSION + ']'; | ||
49 | }; | ||
50 | |||
51 | MochiKit.DragAndDrop.toString = function () { | ||
52 | return this.__repr__(); | ||
53 | }; | ||
54 | |||
55 | MochiKit.DragAndDrop.EXPORT = [ | ||
56 | "Droppable", | ||
57 | "Draggable" | ||
58 | ]; | ||
59 | |||
60 | MochiKit.DragAndDrop.EXPORT_OK = [ | ||
61 | "Droppables", | ||
62 | "Draggables" | ||
63 | ]; | ||
64 | |||
65 | MochiKit.DragAndDrop.Droppables = { | ||
66 | /*** | ||
67 | |||
68 | Manage all droppables. Shouldn't be used, use the Droppable object instead. | ||
69 | |||
70 | ***/ | ||
71 | drops: [], | ||
72 | |||
73 | remove: function (element) { | ||
74 | this.drops = MochiKit.Base.filter(function (d) { | ||
75 | return d.element != MochiKit.DOM.getElement(element); | ||
76 | }, this.drops); | ||
77 | }, | ||
78 | |||
79 | register: function (drop) { | ||
80 | this.drops.push(drop); | ||
81 | }, | ||
82 | |||
83 | unregister: function (drop) { | ||
84 | this.drops = MochiKit.Base.filter(function (d) { | ||
85 | return d != drop; | ||
86 | }, this.drops); | ||
87 | }, | ||
88 | |||
89 | prepare: function (element) { | ||
90 | MochiKit.Base.map(function (drop) { | ||
91 | if (drop.isAccepted(element)) { | ||
92 | if (drop.options.activeclass) { | ||
93 | MochiKit.DOM.addElementClass(drop.element, | ||
94 | drop.options.activeclass); | ||
95 | } | ||
96 | drop.options.onactive(drop.element, element); | ||
97 | } | ||
98 | }, this.drops); | ||
99 | }, | ||
100 | |||
101 | findDeepestChild: function (drops) { | ||
102 | deepest = drops[0]; | ||
103 | |||
104 | for (i = 1; i < drops.length; ++i) { | ||
105 | if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) { | ||
106 | deepest = drops[i]; | ||
107 | } | ||
108 | } | ||
109 | return deepest; | ||
110 | }, | ||
111 | |||
112 | show: function (point, element) { | ||
113 | if (!this.drops.length) { | ||
114 | return; | ||
115 | } | ||
116 | var affected = []; | ||
117 | |||
118 | if (this.last_active) { | ||
119 | this.last_active.deactivate(); | ||
120 | } | ||
121 | MochiKit.Iter.forEach(this.drops, function (drop) { | ||
122 | if (drop.isAffected(point, element)) { | ||
123 | affected.push(drop); | ||
124 | } | ||
125 | }); | ||
126 | if (affected.length > 0) { | ||
127 | drop = this.findDeepestChild(affected); | ||
128 | MochiKit.Position.within(drop.element, point.page.x, point.page.y); | ||
129 | drop.options.onhover(element, drop.element, | ||
130 | MochiKit.Position.overlap(drop.options.overlap, drop.element)); | ||
131 | drop.activate(); | ||
132 | } | ||
133 | }, | ||
134 | |||
135 | fire: function (event, element) { | ||
136 | if (!this.last_active) { | ||
137 | return; | ||
138 | } | ||
139 | MochiKit.Position.prepare(); | ||
140 | |||
141 | if (this.last_active.isAffected(event.mouse(), element)) { | ||
142 | this.last_active.options.ondrop(element, | ||
143 | this.last_active.element, event); | ||
144 | } | ||
145 | }, | ||
146 | |||
147 | reset: function (element) { | ||
148 | MochiKit.Base.map(function (drop) { | ||
149 | if (drop.options.activeclass) { | ||
150 | MochiKit.DOM.removeElementClass(drop.element, | ||
151 | drop.options.activeclass); | ||
152 | } | ||
153 | drop.options.ondesactive(drop.element, element); | ||
154 | }, this.drops); | ||
155 | if (this.last_active) { | ||
156 | this.last_active.deactivate(); | ||
157 | } | ||
158 | } | ||
159 | }; | ||
160 | |||
161 | /** @id MochiKit.DragAndDrop.Droppable */ | ||
162 | MochiKit.DragAndDrop.Droppable = function (element, options) { | ||
163 | var cls = arguments.callee; | ||
164 | if (!(this instanceof cls)) { | ||
165 | return new cls(element, options); | ||
166 | } | ||
167 | this.__init__(element, options); | ||
168 | }; | ||
169 | |||
170 | MochiKit.DragAndDrop.Droppable.prototype = { | ||
171 | /*** | ||
172 | |||
173 | A droppable object. Simple use is to create giving an element: | ||
174 | |||
175 | new MochiKit.DragAndDrop.Droppable('myelement'); | ||
176 | |||
177 | Generally you'll want to define the 'ondrop' function and maybe the | ||
178 | 'accept' option to filter draggables. | ||
179 | |||
180 | ***/ | ||
181 | __class__: MochiKit.DragAndDrop.Droppable, | ||
182 | |||
183 | __init__: function (element, /* optional */options) { | ||
184 | var d = MochiKit.DOM; | ||
185 | var b = MochiKit.Base; | ||
186 | this.element = d.getElement(element); | ||
187 | this.options = b.update({ | ||
188 | |||
189 | /** @id MochiKit.DragAndDrop.greedy */ | ||
190 | greedy: true, | ||
191 | |||
192 | /** @id MochiKit.DragAndDrop.hoverclass */ | ||
193 | hoverclass: null, | ||
194 | |||
195 | /** @id MochiKit.DragAndDrop.activeclass */ | ||
196 | activeclass: null, | ||
197 | |||
198 | /** @id MochiKit.DragAndDrop.hoverfunc */ | ||
199 | hoverfunc: b.noop, | ||
200 | |||
201 | /** @id MochiKit.DragAndDrop.accept */ | ||
202 | accept: null, | ||
203 | |||
204 | /** @id MochiKit.DragAndDrop.onactive */ | ||
205 | onactive: b.noop, | ||
206 | |||
207 | /** @id MochiKit.DragAndDrop.ondesactive */ | ||
208 | ondesactive: b.noop, | ||
209 | |||
210 | /** @id MochiKit.DragAndDrop.onhover */ | ||
211 | onhover: b.noop, | ||
212 | |||
213 | /** @id MochiKit.DragAndDrop.ondrop */ | ||
214 | ondrop: b.noop, | ||
215 | |||
216 | /** @id MochiKit.DragAndDrop.containment */ | ||
217 | containment: [], | ||
218 | tree: false | ||
219 | }, options || {}); | ||
220 | |||
221 | // cache containers | ||
222 | this.options._containers = []; | ||
223 | b.map(MochiKit.Base.bind(function (c) { | ||
224 | this.options._containers.push(d.getElement(c)); | ||
225 | }, this), this.options.containment); | ||
226 | |||
227 | d.makePositioned(this.element); // fix IE | ||
228 | |||
229 | MochiKit.DragAndDrop.Droppables.register(this); | ||
230 | }, | ||
231 | |||
232 | /** @id MochiKit.DragAndDrop.isContained */ | ||
233 | isContained: function (element) { | ||
234 | if (this.options._containers.length) { | ||
235 | var containmentNode; | ||
236 | if (this.options.tree) { | ||
237 | containmentNode = element.treeNode; | ||
238 | } else { | ||
239 | containmentNode = element.parentNode; | ||
240 | } | ||
241 | return MochiKit.Iter.some(this.options._containers, function (c) { | ||
242 | return containmentNode == c; | ||
243 | }); | ||
244 | } else { | ||
245 | return true; | ||
246 | } | ||
247 | }, | ||
248 | |||
249 | /** @id MochiKit.DragAndDrop.isAccepted */ | ||
250 | isAccepted: function (element) { | ||
251 | return ((!this.options.accept) || MochiKit.Iter.some( | ||
252 | this.options.accept, function (c) { | ||
253 | return MochiKit.DOM.hasElementClass(element, c); | ||
254 | })); | ||
255 | }, | ||
256 | |||
257 | /** @id MochiKit.DragAndDrop.isAffected */ | ||
258 | isAffected: function (point, element) { | ||
259 | return ((this.element != element) && | ||
260 | this.isContained(element) && | ||
261 | this.isAccepted(element) && | ||
262 | MochiKit.Position.within(this.element, point.page.x, | ||
263 | point.page.y)); | ||
264 | }, | ||
265 | |||
266 | /** @id MochiKit.DragAndDrop.deactivate */ | ||
267 | deactivate: function () { | ||
268 | /*** | ||
269 | |||
270 | A droppable is deactivate when a draggable has been over it and left. | ||
271 | |||
272 | ***/ | ||
273 | if (this.options.hoverclass) { | ||
274 | MochiKit.DOM.removeElementClass(this.element, | ||
275 | this.options.hoverclass); | ||
276 | } | ||
277 | this.options.hoverfunc(this.element, false); | ||
278 | MochiKit.DragAndDrop.Droppables.last_active = null; | ||
279 | }, | ||
280 | |||
281 | /** @id MochiKit.DragAndDrop.activate */ | ||
282 | activate: function () { | ||
283 | /*** | ||
284 | |||
285 | A droppable is active when a draggable is over it. | ||
286 | |||
287 | ***/ | ||
288 | if (this.options.hoverclass) { | ||
289 | MochiKit.DOM.addElementClass(this.element, this.options.hoverclass); | ||
290 | } | ||
291 | this.options.hoverfunc(this.element, true); | ||
292 | MochiKit.DragAndDrop.Droppables.last_active = this; | ||
293 | }, | ||
294 | |||
295 | /** @id MochiKit.DragAndDrop.destroy */ | ||
296 | destroy: function () { | ||
297 | /*** | ||
298 | |||
299 | Delete this droppable. | ||
300 | |||
301 | ***/ | ||
302 | MochiKit.DragAndDrop.Droppables.unregister(this); | ||
303 | }, | ||
304 | |||
305 | /** @id MochiKit.DragAndDrop.repr */ | ||
306 | repr: function () { | ||
307 | return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; | ||
308 | } | ||
309 | }; | ||
310 | |||
311 | MochiKit.DragAndDrop.Draggables = { | ||
312 | /*** | ||
313 | |||
314 | Manage draggables elements. Not intended to direct use. | ||
315 | |||
316 | ***/ | ||
317 | drags: [], | ||
318 | |||
319 | register: function (draggable) { | ||
320 | if (this.drags.length === 0) { | ||
321 | var conn = MochiKit.Signal.connect; | ||
322 | this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag); | ||
323 | this.eventMouseMove = conn(document, 'onmousemove', this, | ||
324 | this.updateDrag); | ||
325 | this.eventKeypress = conn(document, 'onkeypress', this, | ||
326 | this.keyPress); | ||
327 | } | ||
328 | this.drags.push(draggable); | ||
329 | }, | ||
330 | |||
331 | unregister: function (draggable) { | ||
332 | this.drags = MochiKit.Base.filter(function (d) { | ||
333 | return d != draggable; | ||
334 | }, this.drags); | ||
335 | if (this.drags.length === 0) { | ||
336 | var disc = MochiKit.Signal.disconnect; | ||
337 | disc(this.eventMouseUp); | ||
338 | disc(this.eventMouseMove); | ||
339 | disc(this.eventKeypress); | ||
340 | } | ||
341 | }, | ||
342 | |||
343 | activate: function (draggable) { | ||
344 | // allows keypress events if window is not currently focused | ||
345 | // fails for Safari | ||
346 | window.focus(); | ||
347 | this.activeDraggable = draggable; | ||
348 | }, | ||
349 | |||
350 | deactivate: function () { | ||
351 | this.activeDraggable = null; | ||
352 | }, | ||
353 | |||
354 | updateDrag: function (event) { | ||
355 | if (!this.activeDraggable) { | ||
356 | return; | ||
357 | } | ||
358 | var pointer = event.mouse(); | ||
359 | // Mozilla-based browsers fire successive mousemove events with | ||
360 | // the same coordinates, prevent needless redrawing (moz bug?) | ||
361 | if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) == | ||
362 | MochiKit.Base.repr(pointer.page))) { | ||
363 | return; | ||
364 | } | ||
365 | this._lastPointer = pointer; | ||
366 | this.activeDraggable.updateDrag(event, pointer); | ||
367 | }, | ||
368 | |||
369 | endDrag: function (event) { | ||
370 | if (!this.activeDraggable) { | ||
371 | return; | ||
372 | } | ||
373 | this._lastPointer = null; | ||
374 | this.activeDraggable.endDrag(event); | ||
375 | this.activeDraggable = null; | ||
376 | }, | ||
377 | |||
378 | keyPress: function (event) { | ||
379 | if (this.activeDraggable) { | ||
380 | this.activeDraggable.keyPress(event); | ||
381 | } | ||
382 | }, | ||
383 | |||
384 | notify: function (eventName, draggable, event) { | ||
385 | MochiKit.Signal.signal(this, eventName, draggable, event); | ||
386 | } | ||
387 | }; | ||
388 | |||
389 | /** @id MochiKit.DragAndDrop.Draggable */ | ||
390 | MochiKit.DragAndDrop.Draggable = function (element, options) { | ||
391 | var cls = arguments.callee; | ||
392 | if (!(this instanceof cls)) { | ||
393 | return new cls(element, options); | ||
394 | } | ||
395 | this.__init__(element, options); | ||
396 | }; | ||
397 | |||
398 | MochiKit.DragAndDrop.Draggable.prototype = { | ||
399 | /*** | ||
400 | |||
401 | A draggable object. Simple instantiate : | ||
402 | |||
403 | new MochiKit.DragAndDrop.Draggable('myelement'); | ||
404 | |||
405 | ***/ | ||
406 | __class__ : MochiKit.DragAndDrop.Draggable, | ||
407 | |||
408 | __init__: function (element, /* optional */options) { | ||
409 | var v = MochiKit.Visual; | ||
410 | var b = MochiKit.Base; | ||
411 | options = b.update({ | ||
412 | |||
413 | /** @id MochiKit.DragAndDrop.handle */ | ||
414 | handle: false, | ||
415 | |||
416 | /** @id MochiKit.DragAndDrop.starteffect */ | ||
417 | starteffect: function (innerelement) { | ||
418 | this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0; | ||
419 | new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7}); | ||
420 | }, | ||
421 | /** @id MochiKit.DragAndDrop.reverteffect */ | ||
422 | reverteffect: function (innerelement, top_offset, left_offset) { | ||
423 | var dur = Math.sqrt(Math.abs(top_offset^2) + | ||
424 | Math.abs(left_offset^2))*0.02; | ||
425 | return new v.Move(innerelement, | ||
426 | {x: -left_offset, y: -top_offset, duration: dur}); | ||
427 | }, | ||
428 | |||
429 | /** @id MochiKit.DragAndDrop.endeffect */ | ||
430 | endeffect: function (innerelement) { | ||
431 | new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity}); | ||
432 | }, | ||
433 | |||
434 | /** @id MochiKit.DragAndDrop.onchange */ | ||
435 | onchange: b.noop, | ||
436 | |||
437 | /** @id MochiKit.DragAndDrop.zindex */ | ||
438 | zindex: 1000, | ||
439 | |||
440 | /** @id MochiKit.DragAndDrop.revert */ | ||
441 | revert: false, | ||
442 | |||
443 | /** @id MochiKit.DragAndDrop.scroll */ | ||
444 | scroll: false, | ||
445 | |||
446 | /** @id MochiKit.DragAndDrop.scrollSensitivity */ | ||
447 | scrollSensitivity: 20, | ||
448 | |||
449 | /** @id MochiKit.DragAndDrop.scrollSpeed */ | ||
450 | scrollSpeed: 15, | ||
451 | // false, or xy or [x, y] or function (x, y){return [x, y];} | ||
452 | |||
453 | /** @id MochiKit.DragAndDrop.snap */ | ||
454 | snap: false | ||
455 | }, options || {}); | ||
456 | |||
457 | var d = MochiKit.DOM; | ||
458 | this.element = d.getElement(element); | ||
459 | |||
460 | if (options.handle && (typeof(options.handle) == 'string')) { | ||
461 | this.handle = d.getFirstElementByTagAndClassName(null, | ||
462 | options.handle, this.element); | ||
463 | } | ||
464 | if (!this.handle) { | ||
465 | this.handle = d.getElement(options.handle); | ||
466 | } | ||
467 | if (!this.handle) { | ||
468 | this.handle = this.element; | ||
469 | } | ||
470 | |||
471 | if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { | ||
472 | options.scroll = d.getElement(options.scroll); | ||
473 | this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll); | ||
474 | } | ||
475 | |||
476 | d.makePositioned(this.element); // fix IE | ||
477 | |||
478 | this.delta = this.currentDelta(); | ||
479 | this.options = options; | ||
480 | this.dragging = false; | ||
481 | |||
482 | this.eventMouseDown = MochiKit.Signal.connect(this.handle, | ||
483 | 'onmousedown', this, this.initDrag); | ||
484 | MochiKit.DragAndDrop.Draggables.register(this); | ||
485 | }, | ||
486 | |||
487 | /** @id MochiKit.DragAndDrop.destroy */ | ||
488 | destroy: function () { | ||
489 | MochiKit.Signal.disconnect(this.eventMouseDown); | ||
490 | MochiKit.DragAndDrop.Draggables.unregister(this); | ||
491 | }, | ||
492 | |||
493 | /** @id MochiKit.DragAndDrop.currentDelta */ | ||
494 | currentDelta: function () { | ||
495 | var s = MochiKit.Style.getStyle; | ||
496 | return [ | ||
497 | parseInt(s(this.element, 'left') || '0'), | ||
498 | parseInt(s(this.element, 'top') || '0')]; | ||
499 | }, | ||
500 | |||
501 | /** @id MochiKit.DragAndDrop.initDrag */ | ||
502 | initDrag: function (event) { | ||
503 | if (!event.mouse().button.left) { | ||
504 | return; | ||
505 | } | ||
506 | // abort on form elements, fixes a Firefox issue | ||
507 | var src = event.target(); | ||
508 | var tagName = (src.tagName || '').toUpperCase(); | ||
509 | if (tagName === 'INPUT' || tagName === 'SELECT' || | ||
510 | tagName === 'OPTION' || tagName === 'BUTTON' || | ||
511 | tagName === 'TEXTAREA') { | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | if (this._revert) { | ||
516 | this._revert.cancel(); | ||
517 | this._revert = null; | ||
518 | } | ||
519 | |||
520 | var pointer = event.mouse(); | ||
521 | var pos = MochiKit.Position.cumulativeOffset(this.element); | ||
522 | this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y]; | ||
523 | |||
524 | MochiKit.DragAndDrop.Draggables.activate(this); | ||
525 | event.stop(); | ||
526 | }, | ||
527 | |||
528 | /** @id MochiKit.DragAndDrop.startDrag */ | ||
529 | startDrag: function (event) { | ||
530 | this.dragging = true; | ||
531 | if (this.options.selectclass) { | ||
532 | MochiKit.DOM.addElementClass(this.element, | ||
533 | this.options.selectclass); | ||
534 | } | ||
535 | if (this.options.zindex) { | ||
536 | this.originalZ = parseInt(MochiKit.Style.getStyle(this.element, | ||
537 | 'z-index') || '0'); | ||
538 | this.element.style.zIndex = this.options.zindex; | ||
539 | } | ||
540 | |||
541 | if (this.options.ghosting) { | ||
542 | this._clone = this.element.cloneNode(true); | ||
543 | this.ghostPosition = MochiKit.Position.absolutize(this.element); | ||
544 | this.element.parentNode.insertBefore(this._clone, this.element); | ||
545 | } | ||
546 | |||
547 | if (this.options.scroll) { | ||
548 | if (this.options.scroll == window) { | ||
549 | var where = this._getWindowScroll(this.options.scroll); | ||
550 | this.originalScrollLeft = where.left; | ||
551 | this.originalScrollTop = where.top; | ||
552 | } else { | ||
553 | this.originalScrollLeft = this.options.scroll.scrollLeft; | ||
554 | this.originalScrollTop = this.options.scroll.scrollTop; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | MochiKit.DragAndDrop.Droppables.prepare(this.element); | ||
559 | MochiKit.DragAndDrop.Draggables.notify('start', this, event); | ||
560 | if (this.options.starteffect) { | ||
561 | this.options.starteffect(this.element); | ||
562 | } | ||
563 | }, | ||
564 | |||
565 | /** @id MochiKit.DragAndDrop.updateDrag */ | ||
566 | updateDrag: function (event, pointer) { | ||
567 | if (!this.dragging) { | ||
568 | this.startDrag(event); | ||
569 | } | ||
570 | MochiKit.Position.prepare(); | ||
571 | MochiKit.DragAndDrop.Droppables.show(pointer, this.element); | ||
572 | MochiKit.DragAndDrop.Draggables.notify('drag', this, event); | ||
573 | this.draw(pointer); | ||
574 | this.options.onchange(this); | ||
575 | |||
576 | if (this.options.scroll) { | ||
577 | this.stopScrolling(); | ||
578 | var p, q; | ||
579 | if (this.options.scroll == window) { | ||
580 | var s = this._getWindowScroll(this.options.scroll); | ||
581 | p = new MochiKit.Style.Coordinates(s.left, s.top); | ||
582 | q = new MochiKit.Style.Coordinates(s.left + s.width, | ||
583 | s.top + s.height); | ||
584 | } else { | ||
585 | p = MochiKit.Position.page(this.options.scroll); | ||
586 | p.x += this.options.scroll.scrollLeft; | ||
587 | p.y += this.options.scroll.scrollTop; | ||
588 | p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0); | ||
589 | p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0); | ||
590 | q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth, | ||
591 | p.y + this.options.scroll.offsetHeight); | ||
592 | } | ||
593 | var speed = [0, 0]; | ||
594 | if (pointer.page.x > (q.x - this.options.scrollSensitivity)) { | ||
595 | speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity); | ||
596 | } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) { | ||
597 | speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity); | ||
598 | } | ||
599 | if (pointer.page.y > (q.y - this.options.scrollSensitivity)) { | ||
600 | speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity); | ||
601 | } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) { | ||
602 | speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity); | ||
603 | } | ||
604 | this.startScrolling(speed); | ||
605 | } | ||
606 | |||
607 | // fix AppleWebKit rendering | ||
608 | if (/AppleWebKit'/.test(navigator.appVersion)) { | ||
609 | window.scrollBy(0, 0); | ||
610 | } | ||
611 | event.stop(); | ||
612 | }, | ||
613 | |||
614 | /** @id MochiKit.DragAndDrop.finishDrag */ | ||
615 | finishDrag: function (event, success) { | ||
616 | var dr = MochiKit.DragAndDrop; | ||
617 | this.dragging = false; | ||
618 | if (this.options.selectclass) { | ||
619 | MochiKit.DOM.removeElementClass(this.element, | ||
620 | this.options.selectclass); | ||
621 | } | ||
622 | |||
623 | if (this.options.ghosting) { | ||
624 | // XXX: from a user point of view, it would be better to remove | ||
625 | // the node only *after* the MochiKit.Visual.Move end when used | ||
626 | // with revert. | ||
627 | MochiKit.Position.relativize(this.element, this.ghostPosition); | ||
628 | MochiKit.DOM.removeElement(this._clone); | ||
629 | this._clone = null; | ||
630 | } | ||
631 | |||
632 | if (success) { | ||
633 | dr.Droppables.fire(event, this.element); | ||
634 | } | ||
635 | dr.Draggables.notify('end', this, event); | ||
636 | |||
637 | var revert = this.options.revert; | ||
638 | if (revert && typeof(revert) == 'function') { | ||
639 | revert = revert(this.element); | ||
640 | } | ||
641 | |||
642 | var d = this.currentDelta(); | ||
643 | if (revert && this.options.reverteffect) { | ||
644 | this._revert = this.options.reverteffect(this.element, | ||
645 | d[1] - this.delta[1], d[0] - this.delta[0]); | ||
646 | } else { | ||
647 | this.delta = d; | ||
648 | } | ||
649 | |||
650 | if (this.options.zindex) { | ||
651 | this.element.style.zIndex = this.originalZ; | ||
652 | } | ||
653 | |||
654 | if (this.options.endeffect) { | ||
655 | this.options.endeffect(this.element); | ||
656 | } | ||
657 | |||
658 | dr.Draggables.deactivate(); | ||
659 | dr.Droppables.reset(this.element); | ||
660 | }, | ||
661 | |||
662 | /** @id MochiKit.DragAndDrop.keyPress */ | ||
663 | keyPress: function (event) { | ||
664 | if (event.key().string != "KEY_ESCAPE") { | ||
665 | return; | ||
666 | } | ||
667 | this.finishDrag(event, false); | ||
668 | event.stop(); | ||
669 | }, | ||
670 | |||
671 | /** @id MochiKit.DragAndDrop.endDrag */ | ||
672 | endDrag: function (event) { | ||
673 | if (!this.dragging) { | ||
674 | return; | ||
675 | } | ||
676 | this.stopScrolling(); | ||
677 | this.finishDrag(event, true); | ||
678 | event.stop(); | ||
679 | }, | ||
680 | |||
681 | /** @id MochiKit.DragAndDrop.draw */ | ||
682 | draw: function (point) { | ||
683 | var pos = MochiKit.Position.cumulativeOffset(this.element); | ||
684 | var d = this.currentDelta(); | ||
685 | pos.x -= d[0]; | ||
686 | pos.y -= d[1]; | ||
687 | |||
688 | if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { | ||
689 | pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft; | ||
690 | pos.y -= this.options.scroll.scrollTop - this.originalScrollTop; | ||
691 | } | ||
692 | |||
693 | var p = [point.page.x - pos.x - this.offset[0], | ||
694 | point.page.y - pos.y - this.offset[1]]; | ||
695 | |||
696 | if (this.options.snap) { | ||
697 | if (typeof(this.options.snap) == 'function') { | ||
698 | p = this.options.snap(p[0], p[1]); | ||
699 | } else { | ||
700 | if (this.options.snap instanceof Array) { | ||
701 | var i = -1; | ||
702 | p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { | ||
703 | i += 1; | ||
704 | return Math.round(v/this.options.snap[i]) * | ||
705 | this.options.snap[i]; | ||
706 | }, this), p); | ||
707 | } else { | ||
708 | p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { | ||
709 | return Math.round(v/this.options.snap) * | ||
710 | this.options.snap; | ||
711 | }, this), p); | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | var style = this.element.style; | ||
716 | if ((!this.options.constraint) || | ||
717 | (this.options.constraint == 'horizontal')) { | ||
718 | style.left = p[0] + 'px'; | ||
719 | } | ||
720 | if ((!this.options.constraint) || | ||
721 | (this.options.constraint == 'vertical')) { | ||
722 | style.top = p[1] + 'px'; | ||
723 | } | ||
724 | if (style.visibility == 'hidden') { | ||
725 | style.visibility = ''; // fix gecko rendering | ||
726 | } | ||
727 | }, | ||
728 | |||
729 | /** @id MochiKit.DragAndDrop.stopScrolling */ | ||
730 | stopScrolling: function () { | ||
731 | if (this.scrollInterval) { | ||
732 | clearInterval(this.scrollInterval); | ||
733 | this.scrollInterval = null; | ||
734 | MochiKit.DragAndDrop.Draggables._lastScrollPointer = null; | ||
735 | } | ||
736 | }, | ||
737 | |||
738 | /** @id MochiKit.DragAndDrop.startScrolling */ | ||
739 | startScrolling: function (speed) { | ||
740 | if (!speed[0] && !speed[1]) { | ||
741 | return; | ||
742 | } | ||
743 | this.scrollSpeed = [speed[0] * this.options.scrollSpeed, | ||
744 | speed[1] * this.options.scrollSpeed]; | ||
745 | this.lastScrolled = new Date(); | ||
746 | this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10); | ||
747 | }, | ||
748 | |||
749 | /** @id MochiKit.DragAndDrop.scroll */ | ||
750 | scroll: function () { | ||
751 | var current = new Date(); | ||
752 | var delta = current - this.lastScrolled; | ||
753 | this.lastScrolled = current; | ||
754 | |||
755 | if (this.options.scroll == window) { | ||
756 | var s = this._getWindowScroll(this.options.scroll); | ||
757 | if (this.scrollSpeed[0] || this.scrollSpeed[1]) { | ||
758 | var dm = delta / 1000; | ||
759 | this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0], | ||
760 | s.top + dm * this.scrollSpeed[1]); | ||
761 | } | ||
762 | } else { | ||
763 | this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; | ||
764 | this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; | ||
765 | } | ||
766 | |||
767 | var d = MochiKit.DragAndDrop; | ||
768 | |||
769 | MochiKit.Position.prepare(); | ||
770 | d.Droppables.show(d.Draggables._lastPointer, this.element); | ||
771 | d.Draggables.notify('drag', this); | ||
772 | if (this._isScrollChild) { | ||
773 | d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer; | ||
774 | d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000; | ||
775 | d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000; | ||
776 | if (d.Draggables._lastScrollPointer.x < 0) { | ||
777 | d.Draggables._lastScrollPointer.x = 0; | ||
778 | } | ||
779 | if (d.Draggables._lastScrollPointer.y < 0) { | ||
780 | d.Draggables._lastScrollPointer.y = 0; | ||
781 | } | ||
782 | this.draw(d.Draggables._lastScrollPointer); | ||
783 | } | ||
784 | |||
785 | this.options.onchange(this); | ||
786 | }, | ||
787 | |||
788 | _getWindowScroll: function (win) { | ||
789 | var vp, w, h; | ||
790 | MochiKit.DOM.withWindow(win, function () { | ||
791 | vp = MochiKit.Style.getViewportPosition(win.document); | ||
792 | }); | ||
793 | if (win.innerWidth) { | ||
794 | w = win.innerWidth; | ||
795 | h = win.innerHeight; | ||
796 | } else if (win.document.documentElement && win.document.documentElement.clientWidth) { | ||
797 | w = win.document.documentElement.clientWidth; | ||
798 | h = win.document.documentElement.clientHeight; | ||
799 | } else { | ||
800 | w = win.document.body.offsetWidth; | ||
801 | h = win.document.body.offsetHeight; | ||
802 | } | ||
803 | return {top: vp.x, left: vp.y, width: w, height: h}; | ||
804 | }, | ||
805 | |||
806 | /** @id MochiKit.DragAndDrop.repr */ | ||
807 | repr: function () { | ||
808 | return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; | ||
809 | } | ||
810 | }; | ||
811 | |||
812 | MochiKit.DragAndDrop.__new__ = function () { | ||
813 | MochiKit.Base.nameFunctions(this); | ||
814 | |||
815 | this.EXPORT_TAGS = { | ||
816 | ":common": this.EXPORT, | ||
817 | ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) | ||
818 | }; | ||
819 | }; | ||
820 | |||
821 | MochiKit.DragAndDrop.__new__(); | ||
822 | |||
823 | MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop); | ||
824 | |||