Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /***
2 MochiKit.DragAndDrop 1.4
4 See <http://mochikit.com/> for documentation, downloads, license, etc.
6 Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
7 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
9 ***/
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 }
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 }
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 }
40 if (typeof(MochiKit.DragAndDrop) == 'undefined') {
41 MochiKit.DragAndDrop = {};
42 }
44 MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop';
45 MochiKit.DragAndDrop.VERSION = '1.4';
47 MochiKit.DragAndDrop.__repr__ = function () {
48 return '[' + this.NAME + ' ' + this.VERSION + ']';
49 };
51 MochiKit.DragAndDrop.toString = function () {
52 return this.__repr__();
53 };
55 MochiKit.DragAndDrop.EXPORT = [
56 "Droppable",
57 "Draggable"
58 ];
60 MochiKit.DragAndDrop.EXPORT_OK = [
61 "Droppables",
62 "Draggables"
63 ];
65 MochiKit.DragAndDrop.Droppables = {
66 /***
68 Manage all droppables. Shouldn't be used, use the Droppable object instead.
70 ***/
71 drops: [],
73 remove: function (element) {
74 this.drops = MochiKit.Base.filter(function (d) {
75 return d.element != MochiKit.DOM.getElement(element)
76 }, this.drops);
77 },
79 register: function (drop) {
80 this.drops.push(drop);
81 },
83 unregister: function (drop) {
84 this.drops = MochiKit.Base.filter(function (d) {
85 return d != drop;
86 }, this.drops);
87 },
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 },
101 findDeepestChild: function (drops) {
102 deepest = drops[0];
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 },
112 show: function (point, element) {
113 if (!this.drops.length) {
114 return;
115 }
116 var affected = [];
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 },
135 fire: function (event, element) {
136 if (!this.last_active) {
137 return;
138 }
139 MochiKit.Position.prepare();
141 if (this.last_active.isAffected(event.mouse(), element)) {
142 this.last_active.options.ondrop(element,
143 this.last_active.element, event);
144 }
145 },
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 };
161 /** @id MochiKit.DragAndDrop.Droppable */
162 MochiKit.DragAndDrop.Droppable = function (element, options) {
163 this.__init__(element, options);
164 };
166 MochiKit.DragAndDrop.Droppable.prototype = {
167 /***
169 A droppable object. Simple use is to create giving an element:
171 new MochiKit.DragAndDrop.Droppable('myelement');
173 Generally you'll want to define the 'ondrop' function and maybe the
174 'accept' option to filter draggables.
176 ***/
177 __class__: MochiKit.DragAndDrop.Droppable,
179 __init__: function (element, /* optional */options) {
180 var d = MochiKit.DOM;
181 var b = MochiKit.Base;
182 this.element = d.getElement(element);
183 this.options = b.update({
185 /** @id MochiKit.DragAndDrop.greedy */
186 greedy: true,
188 /** @id MochiKit.DragAndDrop.hoverclass */
189 hoverclass: null,
191 /** @id MochiKit.DragAndDrop.activeclass */
192 activeclass: null,
194 /** @id MochiKit.DragAndDrop.hoverfunc */
195 hoverfunc: b.noop,
197 /** @id MochiKit.DragAndDrop.accept */
198 accept: null,
200 /** @id MochiKit.DragAndDrop.onactive */
201 onactive: b.noop,
203 /** @id MochiKit.DragAndDrop.ondesactive */
204 ondesactive: b.noop,
206 /** @id MochiKit.DragAndDrop.onhover */
207 onhover: b.noop,
209 /** @id MochiKit.DragAndDrop.ondrop */
210 ondrop: b.noop,
212 /** @id MochiKit.DragAndDrop.containment */
213 containment: [],
214 tree: false
215 }, options || {});
217 // cache containers
218 this.options._containers = [];
219 b.map(MochiKit.Base.bind(function (c) {
220 this.options._containers.push(d.getElement(c));
221 }, this), this.options.containment);
223 d.makePositioned(this.element); // fix IE
225 MochiKit.DragAndDrop.Droppables.register(this);
226 },
228 /** @id MochiKit.DragAndDrop.isContained */
229 isContained: function (element) {
230 if (this.options._containers.length) {
231 var containmentNode;
232 if (this.options.tree) {
233 containmentNode = element.treeNode;
234 } else {
235 containmentNode = element.parentNode;
236 }
237 return MochiKit.Iter.some(this.options._containers, function (c) {
238 return containmentNode == c;
239 });
240 } else {
241 return true;
242 }
243 },
245 /** @id MochiKit.DragAndDrop.isAccepted */
246 isAccepted: function (element) {
247 return ((!this.options.accept) || MochiKit.Iter.some(
248 this.options.accept, function (c) {
249 return MochiKit.DOM.hasElementClass(element, c);
250 }));
251 },
253 /** @id MochiKit.DragAndDrop.isAffected */
254 isAffected: function (point, element) {
255 return ((this.element != element) &&
256 this.isContained(element) &&
257 this.isAccepted(element) &&
258 MochiKit.Position.within(this.element, point.page.x,
259 point.page.y));
260 },
262 /** @id MochiKit.DragAndDrop.deactivate */
263 deactivate: function () {
264 /***
266 A droppable is deactivate when a draggable has been over it and left.
268 ***/
269 if (this.options.hoverclass) {
270 MochiKit.DOM.removeElementClass(this.element,
271 this.options.hoverclass);
272 }
273 this.options.hoverfunc(this.element, false);
274 MochiKit.DragAndDrop.Droppables.last_active = null;
275 },
277 /** @id MochiKit.DragAndDrop.activate */
278 activate: function () {
279 /***
281 A droppable is active when a draggable is over it.
283 ***/
284 if (this.options.hoverclass) {
285 MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
286 }
287 this.options.hoverfunc(this.element, true);
288 MochiKit.DragAndDrop.Droppables.last_active = this;
289 },
291 /** @id MochiKit.DragAndDrop.destroy */
292 destroy: function () {
293 /***
295 Delete this droppable.
297 ***/
298 MochiKit.DragAndDrop.Droppables.unregister(this);
299 },
301 /** @id MochiKit.DragAndDrop.repr */
302 repr: function () {
303 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
304 }
305 };
307 MochiKit.DragAndDrop.Draggables = {
308 /***
310 Manage draggables elements. Not intended to direct use.
312 ***/
313 drags: [],
315 register: function (draggable) {
316 if (this.drags.length === 0) {
317 var conn = MochiKit.Signal.connect;
318 this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
319 this.eventMouseMove = conn(document, 'onmousemove', this,
320 this.updateDrag);
321 this.eventKeypress = conn(document, 'onkeypress', this,
322 this.keyPress);
323 }
324 this.drags.push(draggable);
325 },
327 unregister: function (draggable) {
328 this.drags = MochiKit.Base.filter(function (d) {
329 return d != draggable;
330 }, this.drags);
331 if (this.drags.length === 0) {
332 var disc = MochiKit.Signal.disconnect
333 disc(this.eventMouseUp);
334 disc(this.eventMouseMove);
335 disc(this.eventKeypress);
336 }
337 },
339 activate: function (draggable) {
340 // allows keypress events if window is not currently focused
341 // fails for Safari
342 window.focus();
343 this.activeDraggable = draggable;
344 },
346 deactivate: function () {
347 this.activeDraggable = null;
348 },
350 updateDrag: function (event) {
351 if (!this.activeDraggable) {
352 return;
353 }
354 var pointer = event.mouse();
355 // Mozilla-based browsers fire successive mousemove events with
356 // the same coordinates, prevent needless redrawing (moz bug?)
357 if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
358 MochiKit.Base.repr(pointer.page))) {
359 return;
360 }
361 this._lastPointer = pointer;
362 this.activeDraggable.updateDrag(event, pointer);
363 },
365 endDrag: function (event) {
366 if (!this.activeDraggable) {
367 return;
368 }
369 this._lastPointer = null;
370 this.activeDraggable.endDrag(event);
371 this.activeDraggable = null;
372 },
374 keyPress: function (event) {
375 if (this.activeDraggable) {
376 this.activeDraggable.keyPress(event);
377 }
378 },
380 notify: function (eventName, draggable, event) {
381 MochiKit.Signal.signal(this, eventName, draggable, event);
382 }
383 };
385 /** @id MochiKit.DragAndDrop.Draggable */
386 MochiKit.DragAndDrop.Draggable = function (element, options) {
387 this.__init__(element, options);
388 };
390 MochiKit.DragAndDrop.Draggable.prototype = {
391 /***
393 A draggable object. Simple instantiate :
395 new MochiKit.DragAndDrop.Draggable('myelement');
397 ***/
398 __class__ : MochiKit.DragAndDrop.Draggable,
400 __init__: function (element, /* optional */options) {
401 var v = MochiKit.Visual;
402 var b = MochiKit.Base;
403 options = b.update({
405 /** @id MochiKit.DragAndDrop.handle */
406 handle: false,
408 /** @id MochiKit.DragAndDrop.starteffect */
409 starteffect: function (innerelement) {
410 this._savedOpacity = MochiKit.Style.getOpacity(innerelement) || 1.0;
411 new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
412 },
413 /** @id MochiKit.DragAndDrop.reverteffect */
414 reverteffect: function (innerelement, top_offset, left_offset) {
415 var dur = Math.sqrt(Math.abs(top_offset^2) +
416 Math.abs(left_offset^2))*0.02;
417 return new v.Move(innerelement,
418 {x: -left_offset, y: -top_offset, duration: dur});
419 },
421 /** @id MochiKit.DragAndDrop.endeffect */
422 endeffect: function (innerelement) {
423 new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
424 },
426 /** @id MochiKit.DragAndDrop.onchange */
427 onchange: b.noop,
429 /** @id MochiKit.DragAndDrop.zindex */
430 zindex: 1000,
432 /** @id MochiKit.DragAndDrop.revert */
433 revert: false,
435 /** @id MochiKit.DragAndDrop.scroll */
436 scroll: false,
438 /** @id MochiKit.DragAndDrop.scrollSensitivity */
439 scrollSensitivity: 20,
441 /** @id MochiKit.DragAndDrop.scrollSpeed */
442 scrollSpeed: 15,
443 // false, or xy or [x, y] or function (x, y){return [x, y];}
445 /** @id MochiKit.DragAndDrop.snap */
446 snap: false
447 }, options || {});
449 var d = MochiKit.DOM;
450 this.element = d.getElement(element);
452 if (options.handle && (typeof(options.handle) == 'string')) {
453 this.handle = d.getFirstElementByTagAndClassName(null,
454 options.handle, this.element);
455 }
456 if (!this.handle) {
457 this.handle = d.getElement(options.handle);
458 }
459 if (!this.handle) {
460 this.handle = this.element;
461 }
463 if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
464 options.scroll = d.getElement(options.scroll);
465 this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
466 }
468 d.makePositioned(this.element); // fix IE
470 this.delta = this.currentDelta();
471 this.options = options;
472 this.dragging = false;
474 this.eventMouseDown = MochiKit.Signal.connect(this.handle,
475 'onmousedown', this, this.initDrag);
476 MochiKit.DragAndDrop.Draggables.register(this);
477 },
479 /** @id MochiKit.DragAndDrop.destroy */
480 destroy: function () {
481 MochiKit.Signal.disconnect(this.eventMouseDown);
482 MochiKit.DragAndDrop.Draggables.unregister(this);
483 },
485 /** @id MochiKit.DragAndDrop.currentDelta */
486 currentDelta: function () {
487 var s = MochiKit.Style.getStyle;
488 return [
489 parseInt(s(this.element, 'left') || '0'),
490 parseInt(s(this.element, 'top') || '0')];
491 },
493 /** @id MochiKit.DragAndDrop.initDrag */
494 initDrag: function (event) {
495 if (!event.mouse().button.left) {
496 return;
497 }
498 // abort on form elements, fixes a Firefox issue
499 var src = event.target();
500 var tagName = (src.tagName || '').toUpperCase();
501 if (tagName === 'INPUT' || tagName === 'SELECT' ||
502 tagName === 'OPTION' || tagName === 'BUTTON' ||
503 tagName === 'TEXTAREA') {
504 return;
505 }
507 if (this._revert) {
508 this._revert.cancel();
509 this._revert = null;
510 }
512 var pointer = event.mouse();
513 var pos = MochiKit.Position.cumulativeOffset(this.element);
514 this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y]
516 MochiKit.DragAndDrop.Draggables.activate(this);
517 event.stop();
518 },
520 /** @id MochiKit.DragAndDrop.startDrag */
521 startDrag: function (event) {
522 this.dragging = true;
523 if (this.options.selectclass) {
524 MochiKit.DOM.addElementClass(this.element,
525 this.options.selectclass);
526 }
527 if (this.options.zindex) {
528 this.originalZ = parseInt(MochiKit.Style.getStyle(this.element,
529 'z-index') || '0');
530 this.element.style.zIndex = this.options.zindex;
531 }
533 if (this.options.ghosting) {
534 this._clone = this.element.cloneNode(true);
535 this.ghostPosition = MochiKit.Position.absolutize(this.element);
536 this.element.parentNode.insertBefore(this._clone, this.element);
537 }
539 if (this.options.scroll) {
540 if (this.options.scroll == window) {
541 var where = this._getWindowScroll(this.options.scroll);
542 this.originalScrollLeft = where.left;
543 this.originalScrollTop = where.top;
544 } else {
545 this.originalScrollLeft = this.options.scroll.scrollLeft;
546 this.originalScrollTop = this.options.scroll.scrollTop;
547 }
548 }
550 MochiKit.DragAndDrop.Droppables.prepare(this.element);
551 MochiKit.DragAndDrop.Draggables.notify('start', this, event);
552 if (this.options.starteffect) {
553 this.options.starteffect(this.element);
554 }
555 },
557 /** @id MochiKit.DragAndDrop.updateDrag */
558 updateDrag: function (event, pointer) {
559 if (!this.dragging) {
560 this.startDrag(event);
561 }
562 MochiKit.Position.prepare();
563 MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
564 MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
565 this.draw(pointer);
566 this.options.onchange(this);
568 if (this.options.scroll) {
569 this.stopScrolling();
570 var p, q;
571 if (this.options.scroll == window) {
572 var s = this._getWindowScroll(this.options.scroll);
573 p = new MochiKit.Style.Coordinates(s.left, s.top);
574 q = new MochiKit.Style.Coordinates(s.left + s.width,
575 s.top + s.height);
576 } else {
577 p = MochiKit.Position.page(this.options.scroll);
578 p.x += this.options.scroll.scrollLeft;
579 p.y += this.options.scroll.scrollTop;
580 p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
581 p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
582 q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
583 p.y + this.options.scroll.offsetHeight);
584 }
585 var speed = [0, 0];
586 if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
587 speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
588 } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
589 speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
590 }
591 if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
592 speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
593 } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
594 speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
595 }
596 this.startScrolling(speed);
597 }
599 // fix AppleWebKit rendering
600 if (/AppleWebKit'/.test(navigator.appVersion)) {
601 window.scrollBy(0, 0);
602 }
603 event.stop();
604 },
606 /** @id MochiKit.DragAndDrop.finishDrag */
607 finishDrag: function (event, success) {
608 var dr = MochiKit.DragAndDrop;
609 this.dragging = false;
610 if (this.options.selectclass) {
611 MochiKit.DOM.removeElementClass(this.element,
612 this.options.selectclass);
613 }
615 if (this.options.ghosting) {
616 // XXX: from a user point of view, it would be better to remove
617 // the node only *after* the MochiKit.Visual.Move end when used
618 // with revert.
619 MochiKit.Position.relativize(this.element, this.ghostPosition);
620 MochiKit.DOM.removeElement(this._clone);
621 this._clone = null;
622 }
624 if (success) {
625 dr.Droppables.fire(event, this.element);
626 }
627 dr.Draggables.notify('end', this, event);
629 var revert = this.options.revert;
630 if (revert && typeof(revert) == 'function') {
631 revert = revert(this.element);
632 }
634 var d = this.currentDelta();
635 if (revert && this.options.reverteffect) {
636 this._revert = this.options.reverteffect(this.element,
637 d[1] - this.delta[1], d[0] - this.delta[0]);
638 } else {
639 this.delta = d;
640 }
642 if (this.options.zindex) {
643 this.element.style.zIndex = this.originalZ;
644 }
646 if (this.options.endeffect) {
647 this.options.endeffect(this.element);
648 }
650 dr.Draggables.deactivate();
651 dr.Droppables.reset(this.element);
652 },
654 /** @id MochiKit.DragAndDrop.keyPress */
655 keyPress: function (event) {
656 if (event.key().string != "KEY_ESCAPE") {
657 return;
658 }
659 this.finishDrag(event, false);
660 event.stop();
661 },
663 /** @id MochiKit.DragAndDrop.endDrag */
664 endDrag: function (event) {
665 if (!this.dragging) {
666 return;
667 }
668 this.stopScrolling();
669 this.finishDrag(event, true);
670 event.stop();
671 },
673 /** @id MochiKit.DragAndDrop.draw */
674 draw: function (point) {
675 var pos = MochiKit.Position.cumulativeOffset(this.element);
676 if (this.options.ghosting) {
677 var r = MochiKit.Position.realOffset(this.element);
678 pos.x += r.x - MochiKit.Position.windowOffset.x;
679 pos.y += r.y - MochiKit.Position.windowOffset.y;
680 }
681 var d = this.currentDelta();
682 pos.x -= d[0];
683 pos.y -= d[1];
685 if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
686 pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
687 pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
688 }
690 var p = [point.page.x - pos.x - this.offset[0],
691 point.page.y - pos.y - this.offset[1]]
693 if (this.options.snap) {
694 if (typeof(this.options.snap) == 'function') {
695 p = this.options.snap(p[0], p[1]);
696 } else {
697 if (this.options.snap instanceof Array) {
698 var i = -1;
699 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
700 i += 1;
701 return Math.round(v/this.options.snap[i]) *
702 this.options.snap[i]
703 }, this), p)
704 } else {
705 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
706 return Math.round(v/this.options.snap) *
707 this.options.snap
708 }, this), p)
709 }
710 }
711 }
712 var style = this.element.style;
713 if ((!this.options.constraint) ||
714 (this.options.constraint == 'horizontal')) {
715 style.left = p[0] + 'px';
716 }
717 if ((!this.options.constraint) ||
718 (this.options.constraint == 'vertical')) {
719 style.top = p[1] + 'px';
720 }
721 if (style.visibility == 'hidden') {
722 style.visibility = ''; // fix gecko rendering
723 }
724 },
726 /** @id MochiKit.DragAndDrop.stopScrolling */
727 stopScrolling: function () {
728 if (this.scrollInterval) {
729 clearInterval(this.scrollInterval);
730 this.scrollInterval = null;
731 MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
732 }
733 },
735 /** @id MochiKit.DragAndDrop.startScrolling */
736 startScrolling: function (speed) {
737 if (!speed[0] && !speed[1]) {
738 return;
739 }
740 this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
741 speed[1] * this.options.scrollSpeed];
742 this.lastScrolled = new Date();
743 this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
744 },
746 /** @id MochiKit.DragAndDrop.scroll */
747 scroll: function () {
748 var current = new Date();
749 var delta = current - this.lastScrolled;
750 this.lastScrolled = current;
752 if (this.options.scroll == window) {
753 var s = this._getWindowScroll(this.options.scroll);
754 if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
755 var d = delta / 1000;
756 this.options.scroll.scrollTo(s.left + d * this.scrollSpeed[0],
757 s.top + d * this.scrollSpeed[1]);
758 }
759 } else {
760 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
761 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
762 }
764 var d = MochiKit.DragAndDrop;
766 MochiKit.Position.prepare();
767 d.Droppables.show(d.Draggables._lastPointer, this.element);
768 d.Draggables.notify('drag', this);
769 if (this._isScrollChild) {
770 d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
771 d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
772 d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
773 if (d.Draggables._lastScrollPointer.x < 0) {
774 d.Draggables._lastScrollPointer.x = 0;
775 }
776 if (d.Draggables._lastScrollPointer.y < 0) {
777 d.Draggables._lastScrollPointer.y = 0;
778 }
779 this.draw(d.Draggables._lastScrollPointer);
780 }
782 this.options.onchange(this);
783 },
785 _getWindowScroll: function (w) {
786 var vp, w, h;
787 MochiKit.DOM.withWindow(w, function () {
788 vp = MochiKit.Style.getViewportPosition(w.document);
789 });
790 if (w.innerWidth) {
791 w = w.innerWidth;
792 h = w.innerHeight;
793 } else if (w.document.documentElement && w.document.documentElement.clientWidth) {
794 w = w.document.documentElement.clientWidth;
795 h = w.document.documentElement.clientHeight;
796 } else {
797 w = w.document.body.offsetWidth;
798 h = w.document.body.offsetHeight
799 }
800 return {top: vp.x, left: vp.y, width: w, height: h};
801 },
803 /** @id MochiKit.DragAndDrop.repr */
804 repr: function () {
805 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
806 }
807 };
809 MochiKit.DragAndDrop.__new__ = function () {
810 MochiKit.Base.nameFunctions(this);
812 this.EXPORT_TAGS = {
813 ":common": this.EXPORT,
814 ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
815 };
816 };
818 MochiKit.DragAndDrop.__new__();
820 MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);