Moveable.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.mdnd.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.mdnd.Moveable"] = true;
  8. dojo.provide("dojox.mdnd.Moveable");
  9. dojo.declare(
  10. "dojox.mdnd.Moveable",
  11. null,
  12. {
  13. // summary:
  14. // Allow end-users to track a DOM node into the web page
  15. // handle: DOMNode
  16. // The node on which the user clicks to drag the main node.
  17. handle: null,
  18. // skip: Boolean
  19. // A flag to control a drag action if a form element has been focused.
  20. // If true, the drag action is not executed.
  21. skip: true,
  22. // dragDistance: Integer
  23. // The user clicks on the handle, but the drag action will really begin
  24. // if he tracks the main node to more than 3 pixels.
  25. dragDistance: 3,
  26. constructor: function(/*Object*/params, /*DOMNode*/node){
  27. // summary:
  28. // Configure parameters and listen to mousedown events from handle
  29. // node.
  30. // params:
  31. // Hash of parameters
  32. // node:
  33. // The draggable node
  34. //console.log("dojox.mdnd.Moveable ::: constructor");
  35. this.node = dojo.byId(node);
  36. this.d = this.node.ownerDocument;
  37. if(!params){ params = {}; }
  38. this.handle = params.handle ? dojo.byId(params.handle) : null;
  39. if(!this.handle){ this.handle = this.node; }
  40. this.skip = params.skip;
  41. this.events = [
  42. dojo.connect(this.handle, "onmousedown", this, "onMouseDown")
  43. ];
  44. if(dojox.mdnd.autoScroll){
  45. this.autoScroll = dojox.mdnd.autoScroll;
  46. }
  47. },
  48. isFormElement: function(/*DOMEvent*/ e){
  49. // summary:
  50. // identify the type of target node associated with a DOM event.
  51. // e:
  52. // a DOM event
  53. // returns:
  54. // if true, the target is one of those specific nodes.
  55. //console.log("dojox.mdnd.Moveable ::: isFormElement");
  56. var t = e.target;
  57. if(t.nodeType == 3 /*TEXT_NODE*/){
  58. t = t.parentNode;
  59. }
  60. return " a button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0; // Boolean
  61. },
  62. onMouseDown: function(/*DOMEvent*/e){
  63. // summary:
  64. // Occurs when the user clicks on the handle node.
  65. // Skip the drag action if a specific node is targeted.
  66. // Listens to mouseup and mousemove events on to the HTML document.
  67. // e:
  68. // a DOM event
  69. // tags:
  70. // callback
  71. //console.log("dojox.mdnd.Moveable ::: onMouseDown");
  72. if(this._isDragging){ return;}
  73. var isLeftButton = (e.which || e.button) == 1;
  74. if(!isLeftButton){
  75. return;
  76. }
  77. if(this.skip && this.isFormElement(e)){ return; }
  78. if(this.autoScroll){
  79. this.autoScroll.setAutoScrollNode(this.node);
  80. this.autoScroll.setAutoScrollMaxPage();
  81. }
  82. this.events.push(dojo.connect(this.d, "onmouseup", this, "onMouseUp"));
  83. this.events.push(dojo.connect(this.d, "onmousemove", this, "onFirstMove"));
  84. this._selectStart = dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent);
  85. this._firstX = e.clientX;
  86. this._firstY = e.clientY;
  87. dojo.stopEvent(e);
  88. },
  89. onFirstMove: function(/*DOMEvent*/e){
  90. // summary:
  91. // Occurs when the user moves the mouse after clicking on the
  92. // handle.
  93. // Determinate when the drag action will have to begin (see
  94. // dragDistance).
  95. // e:
  96. // A DOM event
  97. // tags:
  98. // callback
  99. //console.log("dojox.mdnd.Moveable ::: onFirstMove");
  100. dojo.stopEvent(e);
  101. var d = (this._firstX - e.clientX) * (this._firstX - e.clientX)
  102. + (this._firstY - e.clientY) * (this._firstY - e.clientY);
  103. if(d > this.dragDistance * this.dragDistance){
  104. this._isDragging = true;
  105. dojo.disconnect(this.events.pop());
  106. dojo.style(this.node, "width", dojo.contentBox(this.node).w + "px");
  107. this.initOffsetDrag(e);
  108. this.events.push(dojo.connect(this.d, "onmousemove", this, "onMove"));
  109. }
  110. },
  111. initOffsetDrag: function(/*DOMEvent*/e){
  112. // summary:
  113. // Initialize the gap between main node coordinates and the clicked point.
  114. // Call the onDragStart method.
  115. // e:
  116. // A DOM event
  117. //console.log("dojox.mdnd.Moveable ::: initOffsetDrag");
  118. this.offsetDrag = { 'l': e.pageX, 't': e.pageY };
  119. var s = this.node.style;
  120. var position = dojo.position(this.node, true);
  121. /*if(s.position == "relative" || s.position == ""){
  122. s.position = "absolute"; // enforcing the absolute mode
  123. }*/
  124. this.offsetDrag.l = position.x - this.offsetDrag.l;
  125. this.offsetDrag.t = position.y - this.offsetDrag.t;
  126. var coords = {
  127. 'x': position.x,
  128. 'y': position.y
  129. };
  130. this.size = {
  131. 'w': position.w,
  132. 'h': position.h
  133. };
  134. // method to catch
  135. this.onDragStart(this.node, coords, this.size);
  136. },
  137. onMove: function(/*DOMEvent*/e){
  138. // summary:
  139. // Occurs when the user moves the mouse.
  140. // Calls the onDrag method.
  141. // e:
  142. // a DOM event
  143. // tags:
  144. // callback
  145. //console.log("dojox.mdnd.Moveable ::: onMove");
  146. dojo.stopEvent(e);
  147. // hack to avoid too many calls to onMove in IE8 causing sometimes slowness
  148. if(dojo.isIE == 8 && new Date() - this.date < 20){
  149. return;
  150. }
  151. if(this.autoScroll){
  152. this.autoScroll.checkAutoScroll(e);
  153. }
  154. var coords = {
  155. 'x': this.offsetDrag.l + e.pageX,
  156. 'y': this.offsetDrag.t + e.pageY
  157. };
  158. var s = this.node.style;
  159. s.left = coords.x + "px";
  160. s.top = coords.y + "px";
  161. // method to catch
  162. this.onDrag(this.node, coords, this.size, {'x':e.pageX, 'y':e.pageY});
  163. if(dojo.isIE == 8){
  164. this.date = new Date();
  165. }
  166. },
  167. onMouseUp: function(/*DOMEvent*/e){
  168. // summary:
  169. // Occurs when the user releases the mouse
  170. // Calls the onDragEnd method.
  171. // e:
  172. // a DOM event
  173. if (this._isDragging){
  174. dojo.stopEvent(e);
  175. this._isDragging = false;
  176. if(this.autoScroll){
  177. this.autoScroll.stopAutoScroll();
  178. }
  179. delete this.onMove;
  180. this.onDragEnd(this.node);
  181. this.node.focus();
  182. }
  183. dojo.disconnect(this.events.pop());
  184. dojo.disconnect(this.events.pop());
  185. },
  186. onDragStart: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size){
  187. // summary:
  188. // Stub function.
  189. // Notes : border box model
  190. // node:
  191. // a DOM node
  192. // coords:
  193. // absolute position of the main node
  194. // size:
  195. // an object encapsulating width an height values
  196. // tags:
  197. // callback
  198. },
  199. onDragEnd: function(/*DOMNode*/node){
  200. // summary:
  201. // Stub function
  202. // Notes : Coordinates don't contain margins
  203. // node:
  204. // a DOM node
  205. // tags:
  206. // callback
  207. },
  208. onDrag: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size, /*Object*/mousePosition){
  209. // summary:
  210. // Stub function.
  211. // Notes : border box model for size value, margin box model for coordinates
  212. // node:
  213. // a DOM node
  214. // coords:
  215. // position of the main node (equals to css left/top properties)
  216. // size:
  217. // an object encapsulating width and height values
  218. // mousePosition:
  219. // coordiantes of mouse
  220. // tags:
  221. // callback
  222. },
  223. destroy: function(){
  224. // summary:
  225. // Delecte associated events
  226. // console.log("dojox.mdnd.Moveable ::: destroy");
  227. dojo.forEach(this.events, dojo.disconnect);
  228. this.events = this.node = null;
  229. }
  230. });
  231. }