You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Etherpad.js 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /* global $, APP, interfaceConfig */
  2. import { getSharedDocumentUrl, setDocumentEditingState } from '../../../react/features/etherpad';
  3. import { getToolboxHeight } from '../../../react/features/toolbox/functions.web';
  4. import Filmstrip from '../videolayout/Filmstrip';
  5. import LargeContainer from '../videolayout/LargeContainer';
  6. import VideoLayout from '../videolayout/VideoLayout';
  7. /**
  8. *
  9. */
  10. function bubbleIframeMouseMove(iframe) {
  11. const existingOnMouseMove = iframe.contentWindow.onmousemove;
  12. iframe.contentWindow.onmousemove = function(e) {
  13. if (existingOnMouseMove) {
  14. existingOnMouseMove(e);
  15. }
  16. const evt = document.createEvent('MouseEvents');
  17. const boundingClientRect = iframe.getBoundingClientRect();
  18. evt.initMouseEvent(
  19. 'mousemove',
  20. true, // bubbles
  21. false, // not cancelable
  22. window,
  23. e.detail,
  24. e.screenX,
  25. e.screenY,
  26. e.clientX + boundingClientRect.left,
  27. e.clientY + boundingClientRect.top,
  28. e.ctrlKey,
  29. e.altKey,
  30. e.shiftKey,
  31. e.metaKey,
  32. e.button,
  33. null // no related element
  34. );
  35. iframe.dispatchEvent(evt);
  36. };
  37. }
  38. /**
  39. * Default Etherpad frame width.
  40. */
  41. const DEFAULT_WIDTH = 640;
  42. /**
  43. * Default Etherpad frame height.
  44. */
  45. const DEFAULT_HEIGHT = 480;
  46. const ETHERPAD_CONTAINER_TYPE = 'etherpad';
  47. /**
  48. * Container for Etherpad iframe.
  49. */
  50. class Etherpad extends LargeContainer {
  51. /**
  52. * Creates new Etherpad object
  53. */
  54. constructor(url) {
  55. super();
  56. const iframe = document.createElement('iframe');
  57. iframe.id = 'etherpadIFrame';
  58. iframe.src = url;
  59. iframe.frameBorder = 0;
  60. iframe.scrolling = 'no';
  61. iframe.width = DEFAULT_WIDTH;
  62. iframe.height = DEFAULT_HEIGHT;
  63. iframe.setAttribute('style', 'visibility: hidden;');
  64. this.container.appendChild(iframe);
  65. iframe.onload = function() {
  66. // eslint-disable-next-line no-self-assign
  67. document.domain = document.domain;
  68. bubbleIframeMouseMove(iframe);
  69. setTimeout(() => {
  70. const doc = iframe.contentDocument;
  71. // the iframes inside of the etherpad are
  72. // not yet loaded when the etherpad iframe is loaded
  73. const outer = doc.getElementsByName('ace_outer')[0];
  74. bubbleIframeMouseMove(outer);
  75. const inner = doc.getElementsByName('ace_inner')[0];
  76. bubbleIframeMouseMove(inner);
  77. }, 2000);
  78. };
  79. this.iframe = iframe;
  80. }
  81. /**
  82. *
  83. */
  84. get isOpen() {
  85. return Boolean(this.iframe);
  86. }
  87. /**
  88. *
  89. */
  90. get container() {
  91. return document.getElementById('etherpad');
  92. }
  93. /**
  94. *
  95. */
  96. resize(containerWidth, containerHeight) {
  97. let height, width;
  98. if (interfaceConfig.VERTICAL_FILMSTRIP) {
  99. height = containerHeight - getToolboxHeight();
  100. width = containerWidth - Filmstrip.getVerticalFilmstripWidth();
  101. } else {
  102. height = containerHeight - Filmstrip.getFilmstripHeight();
  103. width = containerWidth;
  104. }
  105. $(this.iframe)
  106. .width(width)
  107. .height(height);
  108. }
  109. /**
  110. *
  111. */
  112. show() {
  113. const $iframe = $(this.iframe);
  114. const $container = $(this.container);
  115. const self = this;
  116. return new Promise(resolve => {
  117. $iframe.fadeIn(300, () => {
  118. self.bodyBackground = document.body.style.background;
  119. document.body.style.background = '#eeeeee';
  120. $iframe.css({ visibility: 'visible' });
  121. $container.css({ zIndex: 2 });
  122. APP.store.dispatch(setDocumentEditingState(true));
  123. resolve();
  124. });
  125. });
  126. }
  127. /**
  128. *
  129. */
  130. hide() {
  131. const $iframe = $(this.iframe);
  132. const $container = $(this.container);
  133. document.body.style.background = this.bodyBackground;
  134. return new Promise(resolve => {
  135. $iframe.fadeOut(300, () => {
  136. $iframe.css({ visibility: 'hidden' });
  137. $container.css({ zIndex: 0 });
  138. APP.store.dispatch(setDocumentEditingState(false));
  139. resolve();
  140. });
  141. });
  142. }
  143. /**
  144. * @return {boolean} do not switch on dominant speaker event if on stage.
  145. */
  146. stayOnStage() {
  147. return true;
  148. }
  149. }
  150. /**
  151. * Manager of the Etherpad frame.
  152. */
  153. export default class EtherpadManager {
  154. /**
  155. *
  156. */
  157. constructor(eventEmitter) {
  158. this.eventEmitter = eventEmitter;
  159. this.etherpad = null;
  160. }
  161. /**
  162. *
  163. */
  164. get isOpen() {
  165. return Boolean(this.etherpad);
  166. }
  167. /**
  168. *
  169. */
  170. isVisible() {
  171. return VideoLayout.isLargeContainerTypeVisible(ETHERPAD_CONTAINER_TYPE);
  172. }
  173. /**
  174. * Create new Etherpad frame.
  175. */
  176. openEtherpad() {
  177. this.etherpad = new Etherpad(getSharedDocumentUrl(APP.store.getState));
  178. VideoLayout.addLargeVideoContainer(
  179. ETHERPAD_CONTAINER_TYPE,
  180. this.etherpad
  181. );
  182. }
  183. /**
  184. * Toggle Etherpad frame visibility.
  185. * Open new Etherpad frame if there is no Etherpad frame yet.
  186. */
  187. toggleEtherpad() {
  188. if (!this.isOpen) {
  189. this.openEtherpad();
  190. }
  191. const isVisible = this.isVisible();
  192. VideoLayout.showLargeVideoContainer(
  193. ETHERPAD_CONTAINER_TYPE, !isVisible);
  194. APP.store.dispatch(setDocumentEditingState(!isVisible));
  195. }
  196. }