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