utils.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { api, converse } from '@converse/headless';
  2. const { u } = converse.env;
  3. export function registerGlobalEventHandlers() {
  4. document.addEventListener('mousemove', onMouseMove);
  5. document.addEventListener('mouseup', onMouseUp);
  6. }
  7. export function unregisterGlobalEventHandlers() {
  8. document.removeEventListener('mousemove', onMouseMove);
  9. document.removeEventListener('mouseup', onMouseUp);
  10. }
  11. /**
  12. * This function registers mousedown and mouseup events hadlers to
  13. * all iframes in the DOM when converse UI resizing events are called
  14. * to prevent mouse drag stutter effect which is bad user experience.
  15. * @param {Element} e - dragging node element.
  16. */
  17. export function dragresizeOverIframeHandler(e) {
  18. const iframes = Array.from(document.getElementsByTagName('iframe'));
  19. for (const iframe of iframes) {
  20. e.addEventListener(
  21. 'mousedown',
  22. () => {
  23. iframe.style.pointerEvents = 'none';
  24. },
  25. { once: true }
  26. );
  27. e.addEventListener(
  28. 'mouseup',
  29. () => {
  30. iframe.style.pointerEvents = 'initial';
  31. },
  32. { once: true }
  33. );
  34. }
  35. }
  36. /**
  37. * @param {import('@converse/headless/types/shared/chatbox').default} model
  38. */
  39. export function initializeDragResize(model) {
  40. const height = model.get('height');
  41. const width = model.get('width');
  42. u.safeSave(model, {
  43. 'height': applyDragResistance(height, model.get('default_height')),
  44. 'width': applyDragResistance(width, model.get('default_width')),
  45. });
  46. }
  47. /**
  48. * @typedef {Object} ResizingData
  49. * @property {HTMLElement} chatbox
  50. * @property {string} direction
  51. */
  52. const resizing = {};
  53. /**
  54. * @returns {string}
  55. */
  56. export function getResizingDirection() {
  57. return resizing.direction;
  58. }
  59. export function onStartVerticalResize(ev, trigger = true) {
  60. if (!api.settings.get('allow_dragresize')) {
  61. return true;
  62. }
  63. ev.preventDefault();
  64. // Record element attributes for mouseMove().
  65. const flyout = u.ancestor(ev.target, '.box-flyout');
  66. const style = window.getComputedStyle(flyout);
  67. const chatbox_el = flyout.parentElement;
  68. chatbox_el.height = parseInt(style.height.replace(/px$/, ''), 10);
  69. resizing.chatbox = chatbox_el;
  70. resizing.direction = 'top';
  71. chatbox_el.prev_pageY = ev.pageY;
  72. if (trigger) {
  73. /**
  74. * Triggered once the user starts to vertically resize a {@link _converse.ChatBoxView}
  75. * @event _converse#startVerticalResize
  76. * @example _converse.api.listen.on('startVerticalResize', (view) => { ... });
  77. */
  78. api.trigger('startVerticalResize', chatbox_el);
  79. }
  80. }
  81. export function onStartHorizontalResize(ev, trigger = true) {
  82. if (!api.settings.get('allow_dragresize')) {
  83. return true;
  84. }
  85. ev.preventDefault();
  86. const flyout = u.ancestor(ev.target, '.box-flyout');
  87. const style = window.getComputedStyle(flyout);
  88. const chatbox_el = flyout.parentElement;
  89. chatbox_el.width = parseInt(style.width.replace(/px$/, ''), 10);
  90. resizing.chatbox = chatbox_el;
  91. resizing.direction = 'left';
  92. chatbox_el.prev_pageX = ev.pageX;
  93. if (trigger) {
  94. /**
  95. * Triggered once the user starts to horizontally resize a {@link _converse.ChatBoxView}
  96. * @event _converse#startHorizontalResize
  97. * @example _converse.api.listen.on('startHorizontalResize', (view) => { ... });
  98. */
  99. api.trigger('startHorizontalResize', chatbox_el);
  100. }
  101. }
  102. export function onStartDiagonalResize(ev) {
  103. onStartHorizontalResize(ev, false);
  104. onStartVerticalResize(ev, false);
  105. resizing.direction = 'topleft';
  106. /**
  107. * Triggered once the user starts to diagonally resize a {@link _converse.ChatBoxView}
  108. * @event _converse#startDiagonalResize
  109. * @example _converse.api.listen.on('startDiagonalResize', (view) => { ... });
  110. */
  111. api.trigger('startDiagonalResize', this);
  112. }
  113. /**
  114. * Applies some resistance to `value` around the `default_value`.
  115. * If value is close enough to `default_value`, then it is returned, otherwise
  116. * `value` is returned.
  117. * @param { number } value
  118. * @param { number } default_value
  119. * @returns { number }
  120. */
  121. export function applyDragResistance(value, default_value) {
  122. if (value === undefined) {
  123. return undefined;
  124. } else if (default_value === undefined) {
  125. return value;
  126. }
  127. const resistance = 10;
  128. if (value !== default_value && Math.abs(value - default_value) < resistance) {
  129. return default_value;
  130. }
  131. return value;
  132. }
  133. export function onMouseMove(ev) {
  134. if (!resizing.chatbox || !api.settings.get('allow_dragresize')) {
  135. return true;
  136. }
  137. ev.preventDefault();
  138. resizing.chatbox.resizeChatBox(ev);
  139. }
  140. export function onMouseUp(ev) {
  141. if (!resizing.chatbox || !api.settings.get('allow_dragresize')) {
  142. return true;
  143. }
  144. ev.preventDefault();
  145. const height = applyDragResistance(resizing.chatbox.height, resizing.chatbox.model.get('default_height'));
  146. const width = applyDragResistance(resizing.chatbox.width, resizing.chatbox.model.get('default_width'));
  147. if (api.connection.connected()) {
  148. resizing.chatbox.model.save({ 'height': height });
  149. resizing.chatbox.model.save({ 'width': width });
  150. } else {
  151. resizing.chatbox.model.set({ 'height': height });
  152. resizing.chatbox.model.set({ 'width': width });
  153. }
  154. delete resizing.chatbox;
  155. delete resizing.direction;
  156. }