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.4KB

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