yzt
2023-05-26 2f70f6727314edd84d8ec2bfe3ce832803f1ea77
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
define([
    "../_base/array", "../_base/declare", "../_base/lang", "../sniff", "../_base/window",
    "../dom", "../dom-geometry", "../dom-style", "../Evented", "../on", "../touch", "./common", "./autoscroll"
], function(array, declare, lang, has, win, dom, domGeom, domStyle, Evented, on, touch, dnd, autoscroll){
 
// module:
//      dojo/dnd/Mover
 
return declare("dojo.dnd.Mover", [Evented], {
    // summary:
    //      an object which makes a node follow the mouse, or touch-drag on touch devices.
    //      Used as a default mover, and as a base class for custom movers.
 
    constructor: function(node, e, host){
        // node: Node
        //      a node (or node's id) to be moved
        // e: Event
        //      a mouse event, which started the move;
        //      only pageX and pageY properties are used
        // host: Object?
        //      object which implements the functionality of the move,
        //      and defines proper events (onMoveStart and onMoveStop)
        this.node = dom.byId(node);
        this.marginBox = {l: e.pageX, t: e.pageY};
        this.mouseButton = e.button;
        var h = (this.host = host), d = node.ownerDocument;
 
        function stopEvent(e){
            e.preventDefault();
            e.stopPropagation();
        }
 
        this.events = [
            // At the start of a drag, onFirstMove is called, and then the following
            // listener is disconnected.
            on(d, touch.move, lang.hitch(this, "onFirstMove")),
 
            // These are called continually during the drag
            on(d, touch.move, lang.hitch(this, "onMouseMove")),
 
            // And these are called at the end of the drag
            on(d, touch.release,  lang.hitch(this, "onMouseUp")),
 
            // cancel text selection and text dragging
            on(d, "dragstart",   stopEvent),
            on(d.body, "selectstart", stopEvent)
        ];
 
        // Tell autoscroll that a drag is starting
        autoscroll.autoScrollStart(d);
 
        // notify that the move has started
        if(h && h.onMoveStart){
            h.onMoveStart(this);
        }
    },
    // mouse event processors
    onMouseMove: function(e){
        // summary:
        //      event processor for onmousemove/ontouchmove
        // e: Event
        //      mouse/touch event
        autoscroll.autoScroll(e);
        var m = this.marginBox;
        this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e);
        e.preventDefault();
        e.stopPropagation();
    },
    onMouseUp: function(e){
        if(has("webkit") && has("mac") && this.mouseButton == 2 ?
                e.button == 0 : this.mouseButton == e.button){ // TODO Should condition be met for touch devices, too?
            this.destroy();
        }
        e.preventDefault();
        e.stopPropagation();
    },
    // utilities
    onFirstMove: function(e){
        // summary:
        //      makes the node absolute; it is meant to be called only once.
        //      relative and absolutely positioned nodes are assumed to use pixel units
        var s = this.node.style, l, t, h = this.host;
        switch(s.position){
            case "relative":
            case "absolute":
                // assume that left and top values are in pixels already
                l = Math.round(parseFloat(s.left)) || 0;
                t = Math.round(parseFloat(s.top)) || 0;
                break;
            default:
                s.position = "absolute";    // enforcing the absolute mode
                var m = domGeom.getMarginBox(this.node);
                // event.pageX/pageY (which we used to generate the initial
                // margin box) includes padding and margin set on the body.
                // However, setting the node's position to absolute and then
                // doing domGeom.marginBox on it *doesn't* take that additional
                // space into account - so we need to subtract the combined
                // padding and margin.  We use getComputedStyle and
                // _getMarginBox/_getContentBox to avoid the extra lookup of
                // the computed style.
                var b = win.doc.body;
                var bs = domStyle.getComputedStyle(b);
                var bm = domGeom.getMarginBox(b, bs);
                var bc = domGeom.getContentBox(b, bs);
                l = m.l - (bc.l - bm.l);
                t = m.t - (bc.t - bm.t);
                break;
        }
        this.marginBox.l = l - this.marginBox.l;
        this.marginBox.t = t - this.marginBox.t;
        if(h && h.onFirstMove){
            h.onFirstMove(this, e);
        }
 
        // Disconnect touch.move that call this function
        this.events.shift().remove();
    },
    destroy: function(){
        // summary:
        //      stops the move, deletes all references, so the object can be garbage-collected
        array.forEach(this.events, function(handle){ handle.remove(); });
        // undo global settings
        var h = this.host;
        if(h && h.onMoveStop){
            h.onMoveStop(this);
        }
        // destroy objects
        this.events = this.node = this.host = null;
    }
});
 
});