Mover.js 3.9 KB

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