dom/tests/mochitest/ajax/mochikit/MochiKit/DragAndDrop.js

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     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     var cls = arguments.callee;
   164     if (!(this instanceof cls)) {
   165         return new cls(element, options);
   166     }
   167     this.__init__(element, options);
   168 };
   170 MochiKit.DragAndDrop.Droppable.prototype = {
   171     /***
   173     A droppable object. Simple use is to create giving an element:
   175         new MochiKit.DragAndDrop.Droppable('myelement');
   177     Generally you'll want to define the 'ondrop' function and maybe the
   178     'accept' option to filter draggables.
   180     ***/
   181     __class__: MochiKit.DragAndDrop.Droppable,
   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({
   189             /** @id MochiKit.DragAndDrop.greedy */
   190             greedy: true,
   192             /** @id MochiKit.DragAndDrop.hoverclass */
   193             hoverclass: null,
   195             /** @id MochiKit.DragAndDrop.activeclass */
   196             activeclass: null,
   198             /** @id MochiKit.DragAndDrop.hoverfunc */
   199             hoverfunc: b.noop,
   201             /** @id MochiKit.DragAndDrop.accept */
   202             accept: null,
   204             /** @id MochiKit.DragAndDrop.onactive */
   205             onactive: b.noop,
   207             /** @id MochiKit.DragAndDrop.ondesactive */
   208             ondesactive: b.noop,
   210             /** @id MochiKit.DragAndDrop.onhover */
   211             onhover: b.noop,
   213             /** @id MochiKit.DragAndDrop.ondrop */
   214             ondrop: b.noop,
   216             /** @id MochiKit.DragAndDrop.containment */
   217             containment: [],
   218             tree: false
   219         }, options || {});
   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);
   227         d.makePositioned(this.element); // fix IE
   229         MochiKit.DragAndDrop.Droppables.register(this);
   230     },
   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     },
   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     },
   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     },
   266     /** @id MochiKit.DragAndDrop.deactivate */
   267     deactivate: function () {
   268         /***
   270         A droppable is deactivate when a draggable has been over it and left.
   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     },
   281     /** @id MochiKit.DragAndDrop.activate */
   282     activate: function () {
   283         /***
   285         A droppable is active when a draggable is over it.
   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     },
   295     /** @id MochiKit.DragAndDrop.destroy */
   296     destroy: function () {
   297         /***
   299         Delete this droppable.
   301         ***/
   302         MochiKit.DragAndDrop.Droppables.unregister(this);
   303     },
   305     /** @id MochiKit.DragAndDrop.repr */
   306     repr: function () {
   307         return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
   308     }
   309 };
   311 MochiKit.DragAndDrop.Draggables = {
   312     /***
   314     Manage draggables elements. Not intended to direct use.
   316     ***/
   317     drags: [],
   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     },
   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     },
   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     },
   350     deactivate: function () {
   351         this.activeDraggable = null;
   352     },
   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     },
   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     },
   378     keyPress: function (event) {
   379         if (this.activeDraggable) {
   380             this.activeDraggable.keyPress(event);
   381         }
   382     },
   384     notify: function (eventName, draggable, event) {
   385         MochiKit.Signal.signal(this, eventName, draggable, event);
   386     }
   387 };
   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 };
   398 MochiKit.DragAndDrop.Draggable.prototype = {
   399     /***
   401     A draggable object. Simple instantiate :
   403         new MochiKit.DragAndDrop.Draggable('myelement');
   405     ***/
   406     __class__ : MochiKit.DragAndDrop.Draggable,
   408     __init__: function (element, /* optional */options) {
   409         var v = MochiKit.Visual;
   410         var b = MochiKit.Base;
   411         options = b.update({
   413             /** @id MochiKit.DragAndDrop.handle */
   414             handle: false,
   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             },
   429             /** @id MochiKit.DragAndDrop.endeffect */
   430             endeffect: function (innerelement) {
   431                 new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
   432             },
   434             /** @id MochiKit.DragAndDrop.onchange */
   435             onchange: b.noop,
   437             /** @id MochiKit.DragAndDrop.zindex */
   438             zindex: 1000,
   440             /** @id MochiKit.DragAndDrop.revert */
   441             revert: false,
   443             /** @id MochiKit.DragAndDrop.scroll */
   444             scroll: false,
   446             /** @id MochiKit.DragAndDrop.scrollSensitivity */
   447             scrollSensitivity: 20,
   449             /** @id MochiKit.DragAndDrop.scrollSpeed */
   450             scrollSpeed: 15,
   451             // false, or xy or [x, y] or function (x, y){return [x, y];}
   453             /** @id MochiKit.DragAndDrop.snap */
   454             snap: false
   455         }, options || {});
   457         var d = MochiKit.DOM;
   458         this.element = d.getElement(element);
   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         }
   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         }
   476         d.makePositioned(this.element);  // fix IE
   478         this.delta = this.currentDelta();
   479         this.options = options;
   480         this.dragging = false;
   482         this.eventMouseDown = MochiKit.Signal.connect(this.handle,
   483                               'onmousedown', this, this.initDrag);
   484         MochiKit.DragAndDrop.Draggables.register(this);
   485     },
   487     /** @id MochiKit.DragAndDrop.destroy */
   488     destroy: function () {
   489         MochiKit.Signal.disconnect(this.eventMouseDown);
   490         MochiKit.DragAndDrop.Draggables.unregister(this);
   491     },
   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     },
   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         }
   515         if (this._revert) {
   516             this._revert.cancel();
   517             this._revert = null;
   518         }
   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];
   524         MochiKit.DragAndDrop.Draggables.activate(this);
   525         event.stop();
   526     },
   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         }
   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         }
   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         }
   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     },
   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);
   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         }
   607         // fix AppleWebKit rendering
   608         if (/AppleWebKit'/.test(navigator.appVersion)) {
   609             window.scrollBy(0, 0);
   610         }
   611         event.stop();
   612     },
   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         }
   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         }
   632         if (success) {
   633             dr.Droppables.fire(event, this.element);
   634         }
   635         dr.Draggables.notify('end', this, event);
   637         var revert = this.options.revert;
   638         if (revert && typeof(revert) == 'function') {
   639             revert = revert(this.element);
   640         }
   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         }
   650         if (this.options.zindex) {
   651             this.element.style.zIndex = this.originalZ;
   652         }
   654         if (this.options.endeffect) {
   655             this.options.endeffect(this.element);
   656         }
   658         dr.Draggables.deactivate();
   659         dr.Droppables.reset(this.element);
   660     },
   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     },
   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     },
   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];
   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         }
   693         var p = [point.page.x - pos.x - this.offset[0],
   694                  point.page.y - pos.y - this.offset[1]];
   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     },
   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     },
   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     },
   749     /** @id MochiKit.DragAndDrop.scroll */
   750     scroll: function () {
   751         var current = new Date();
   752         var delta = current - this.lastScrolled;
   753         this.lastScrolled = current;
   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         }
   767         var d = MochiKit.DragAndDrop;
   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         }
   785         this.options.onchange(this);
   786     },
   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     },
   806     /** @id MochiKit.DragAndDrop.repr */
   807     repr: function () {
   808         return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
   809     }
   810 };
   812 MochiKit.DragAndDrop.__new__ = function () {
   813     MochiKit.Base.nameFunctions(this);
   815     this.EXPORT_TAGS = {
   816         ":common": this.EXPORT,
   817         ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
   818     };
   819 };
   821 MochiKit.DragAndDrop.__new__();
   823 MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);

mercurial