testing/mochitest/tests/MochiKit-1.4.2/MochiKit/DragAndDrop.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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

mercurial