resizedrag.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. let _loaded = false;
  2. let _callbacks = [];
  3. const _isTouch = window.ontouchstart !== undefined;
  4. const resizedrag = function(target, handler, onStart, onEnd) {
  5. let config = {
  6. dragEnabled : target.dataset.rdDragEnabled !== "false",
  7. resizeEnabled : target.dataset.rdResizeEnabled !== "false",
  8. dragBorderEnabled : target.dataset.rdDragBorderEnabled !== "false",
  9. rdDragBoundary : target.dataset.rdDragBoundary === "true",
  10. minWidth : target.dataset.rdMinWidth ? target.dataset.rdMinWidth : 5 ,
  11. minHeight : target.dataset.rdMinHeight ? target.dataset.rdMinHeight : 5
  12. }
  13. let MARGINS = 4;
  14. let edges = {
  15. top : false,
  16. bottom : false,
  17. left : false,
  18. right : false,
  19. }
  20. let targetElement = document.getElementById(target.id);
  21. let clickedInstance ;
  22. let eventHandlers = {
  23. mousemove : function(e) {
  24. let c = e;
  25. if(e.touches) {
  26. c = e.touches[0];
  27. }
  28. // On mouse move, dispatch the coords to all registered callbacks.
  29. for (var i = 0; i < _callbacks.length; i++) {
  30. _callbacks[i](c.clientX, c.clientY);
  31. }
  32. },
  33. mousedown : function(e) {
  34. e.stopPropagation();
  35. e.preventDefault();
  36. if (!config.dragEnabled && !config.resizeEnabled) {
  37. return;
  38. }
  39. let c = e;
  40. if (e.touches) {
  41. c = e.touches[0];
  42. }
  43. isMoving = true;
  44. let bObj = attachResizeDragCursorStyle(c.clientX,c.clientY);
  45. clickedInstance = {
  46. cx : c.clientX,
  47. cy : c.clientY,
  48. w: bObj.b.width,
  49. h: bObj.b.height
  50. }
  51. isResizing = edges.right || edges.bottom || edges.top || edges.left;
  52. if(!isResizing){
  53. target.style["border-style"]="dashed";
  54. target.style["border-color"]="grey";
  55. target.style["border-width"]="2px";
  56. }
  57. startX = target.offsetLeft - c.clientX;
  58. startY = target.offsetTop - c.clientY;
  59. },
  60. mouseup : function(e) {
  61. if (onEnd && hasStarted) {
  62. onEnd(target, parseInt(target.style.left), parseInt(target.style.top));
  63. }
  64. let c = e;
  65. attachResizeDragCursorStyle(c.clientX,c.clientY);
  66. isResizing = false;
  67. isMoving = false;
  68. hasStarted = false;
  69. target.style["border"]="none";
  70. }
  71. }
  72. // Register a global event to capture mouse moves (once).
  73. if (!_loaded) {
  74. document.addEventListener(_isTouch ? "touchmove" : "mousemove", eventHandlers.mousemove);
  75. }
  76. _loaded = true;
  77. let isMoving = false, hasStarted = false, isResizing = false;
  78. let startX = 0, startY = 0, lastX = 0, lastY = 0;
  79. // On the first click and hold, record the offset of the pointer in relation
  80. // to the point of click inside the element.
  81. handler.addEventListener(_isTouch ? "touchstart" : "mousedown", eventHandlers.mousedown);
  82. // On leaving click, stop moving.
  83. document.addEventListener(_isTouch ? "touchend" : "mouseup", eventHandlers.mouseup);
  84. // Register mouse-move callback to move the element.
  85. _callbacks.push(function move(x, y) {
  86. if(targetElement && !isResizing){
  87. attachResizeDragCursorStyle(x,y);
  88. }
  89. if (!isMoving) {
  90. return;
  91. }
  92. if (!hasStarted) {
  93. hasStarted = true;
  94. if (onStart) {
  95. onStart(target, lastX, lastY);
  96. }
  97. }
  98. lastX = x + startX;
  99. lastY = y + startY;
  100. // If boundary checking is on, don't let the element cross the viewport.
  101. if (config.rdDragBoundary) {
  102. if (lastX < 1 || lastX >= window.innerWidth - target.offsetWidth) {
  103. return;
  104. }
  105. if (lastY < 1 || lastY >= window.innerHeight - target.offsetHeight) {
  106. return;
  107. }
  108. }
  109. if(isMoving){
  110. if(!isResizing && config.dragEnabled){
  111. target.style.left = lastX + "px";
  112. target.style.top = lastY + "px";
  113. }else{
  114. if(config.resizeEnabled){
  115. let b = target.getBoundingClientRect();
  116. let bx = x - b.left;
  117. let by = y - b.top;
  118. if (edges.right) {
  119. target.style.width = Math.max(bx, config.minWidth) + 'px';
  120. }
  121. if (edges.bottom) {
  122. target.style.height = Math.max(by, config.minHeight) + 'px';
  123. }
  124. if (edges.left) {
  125. var currentWidth = Math.max(clickedInstance.cx - x + clickedInstance.w, config.minWidth);
  126. if (currentWidth > config.minWidth) {
  127. target.style.width = currentWidth + 'px';
  128. target.style.left = x + 'px';
  129. }
  130. }
  131. if (edges.top) {
  132. var currentHeight = Math.max(clickedInstance.cy - y + clickedInstance.h, config.minHeight);
  133. if (currentHeight > config.minHeight) {
  134. targetElement.style.height = currentHeight + 'px';
  135. targetElement.style.top = y + 'px';
  136. }
  137. }
  138. }
  139. }
  140. }
  141. });
  142. let attachResizeDragCursorStyle = function(x,y){
  143. let b = target.getBoundingClientRect();
  144. let eX = x - b.left;
  145. let eY = y - b.top;
  146. edges.top = eY < MARGINS;
  147. edges.left = eX < MARGINS;
  148. edges.right = eX >= b.width - MARGINS;
  149. edges.bottom = eY >= b.height - MARGINS;
  150. if (edges.right && edges.bottom || edges.left && edges.top) {
  151. targetElement.style.cursor = 'nwse-resize';
  152. } else if (edges.right && edges.top || edges.bottom && edges.left) {
  153. targetElement.style.cursor = 'nesw-resize';
  154. } else if (edges.right || edges.left) {
  155. targetElement.style.cursor = 'ew-resize';
  156. } else if (edges.bottom || edges.top) {
  157. targetElement.style.cursor = 'ns-resize';
  158. } else if(eX > 0 && eX < b.width && eY > 0 && eY < b.height){
  159. targetElement.style.cursor = config.dragEnabled ?'move':'not-allowed';
  160. }else {
  161. targetElement.style.cursor = 'default';
  162. }
  163. let boundaryObj = {
  164. b:b, bX : eX, bY : eY
  165. }
  166. return boundaryObj
  167. }
  168. }
  169. export { resizedrag };