testing/mochitest/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
     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);

mercurial