toolkit/javascript/d3/src/behavior/drag.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 d3.behavior.drag = function() {
       
     2   var event = d3.dispatch("drag", "dragstart", "dragend");
       
     3 
       
     4   function drag() {
       
     5     this
       
     6         .on("mousedown.drag", mousedown)
       
     7         .on("touchstart.drag", mousedown);
       
     8 
       
     9     d3.select(window)
       
    10         .on("mousemove.drag", d3_behavior_dragMove)
       
    11         .on("touchmove.drag", d3_behavior_dragMove)
       
    12         .on("mouseup.drag", d3_behavior_dragUp, true)
       
    13         .on("touchend.drag", d3_behavior_dragUp, true)
       
    14         .on("click.drag", d3_behavior_dragClick, true);
       
    15   }
       
    16 
       
    17   // snapshot the local context for subsequent dispatch
       
    18   function start() {
       
    19     d3_behavior_dragEvent = event;
       
    20     d3_behavior_dragEventTarget = d3.event.target;
       
    21     d3_behavior_dragOffset = d3_behavior_dragPoint((d3_behavior_dragTarget = this).parentNode);
       
    22     d3_behavior_dragMoved = 0;
       
    23     d3_behavior_dragArguments = arguments;
       
    24   }
       
    25 
       
    26   function mousedown() {
       
    27     start.apply(this, arguments);
       
    28     d3_behavior_dragDispatch("dragstart");
       
    29   }
       
    30 
       
    31   drag.on = function(type, listener) {
       
    32     event.on(type, listener);
       
    33     return drag;
       
    34   };
       
    35 
       
    36   return drag;
       
    37 };
       
    38 
       
    39 var d3_behavior_dragEvent,
       
    40     d3_behavior_dragEventTarget,
       
    41     d3_behavior_dragTarget,
       
    42     d3_behavior_dragArguments,
       
    43     d3_behavior_dragOffset,
       
    44     d3_behavior_dragMoved,
       
    45     d3_behavior_dragStopClick;
       
    46 
       
    47 function d3_behavior_dragDispatch(type) {
       
    48   var o = d3.event, p = d3_behavior_dragTarget.parentNode, dx = 0, dy = 0;
       
    49 
       
    50   if (p) {
       
    51     p = d3_behavior_dragPoint(p);
       
    52     dx = p[0] - d3_behavior_dragOffset[0];
       
    53     dy = p[1] - d3_behavior_dragOffset[1];
       
    54     d3_behavior_dragOffset = p;
       
    55     d3_behavior_dragMoved |= dx | dy;
       
    56   }
       
    57 
       
    58   try {
       
    59     d3.event = {dx: dx, dy: dy};
       
    60     d3_behavior_dragEvent[type].apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
       
    61   } finally {
       
    62     d3.event = o;
       
    63   }
       
    64 
       
    65   o.preventDefault();
       
    66 }
       
    67 
       
    68 function d3_behavior_dragPoint(container, type) {
       
    69   // TODO Track touch points by identifier.
       
    70   var t = d3.event.changedTouches;
       
    71   return t ? d3.svg.touches(container, t)[0] : d3.svg.mouse(container);
       
    72 }
       
    73 
       
    74 function d3_behavior_dragMove() {
       
    75   if (!d3_behavior_dragTarget) return;
       
    76   var parent = d3_behavior_dragTarget.parentNode;
       
    77 
       
    78   // O NOES! The drag element was removed from the DOM.
       
    79   if (!parent) return d3_behavior_dragUp();
       
    80 
       
    81   d3_behavior_dragDispatch("drag");
       
    82   d3_eventCancel();
       
    83 }
       
    84 
       
    85 function d3_behavior_dragUp() {
       
    86   if (!d3_behavior_dragTarget) return;
       
    87   d3_behavior_dragDispatch("dragend");
       
    88   d3_behavior_dragTarget = null;
       
    89 
       
    90   // If the node was moved, prevent the mouseup from propagating.
       
    91   // Also prevent the subsequent click from propagating (e.g., for anchors).
       
    92   if (d3_behavior_dragMoved && d3_behavior_dragEventTarget === d3.event.target) {
       
    93     d3_behavior_dragStopClick = true;
       
    94     d3_eventCancel();
       
    95   }
       
    96 }
       
    97 
       
    98 function d3_behavior_dragClick() {
       
    99   if (d3_behavior_dragStopClick && d3_behavior_dragEventTarget === d3.event.target) {
       
   100     d3_eventCancel();
       
   101     d3_behavior_dragStopClick = false;
       
   102     d3_behavior_dragEventTarget = null;
       
   103   }
       
   104 }