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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. function bubbleIframeMouseMove(iframe){
  16. var existingOnMouseMove = iframe.contentWindow.onmousemove;
  17. iframe.contentWindow.onmousemove = function(e){
  18. if(existingOnMouseMove) existingOnMouseMove(e);
  19. var evt = document.createEvent("MouseEvents");
  20. var boundingClientRect = iframe.getBoundingClientRect();
  21. evt.initMouseEvent(
  22. "mousemove",
  23. true, // bubbles
  24. false, // not cancelable
  25. window,
  26. e.detail,
  27. e.screenX,
  28. e.screenY,
  29. e.clientX + boundingClientRect.left,
  30. e.clientY + boundingClientRect.top,
  31. e.ctrlKey,
  32. e.altKey,
  33. e.shiftKey,
  34. e.metaKey,
  35. e.button,
  36. null // no related element
  37. );
  38. iframe.dispatchEvent(evt);
  39. };
  40. }
  41. /**
  42. * Default Etherpad frame width.
  43. */
  44. const DEFAULT_WIDTH = 640;
  45. /**
  46. * Default Etherpad frame height.
  47. */
  48. const DEFAULT_HEIGHT = 480;
  49. const ETHERPAD_CONTAINER_TYPE = "etherpad";
  50. /**
  51. * Container for Etherpad iframe.
  52. */
  53. class Etherpad extends LargeContainer {
  54. constructor (domain, name) {
  55. super();
  56. const iframe = document.createElement('iframe');
  57. iframe.src = domain + name + '?' + options;
  58. iframe.frameBorder = 0;
  59. iframe.scrolling = "no";
  60. iframe.width = DEFAULT_WIDTH;
  61. iframe.height = DEFAULT_HEIGHT;
  62. iframe.setAttribute('style', 'visibility: hidden;');
  63. this.container.appendChild(iframe);
  64. iframe.onload = function() {
  65. document.domain = document.domain;
  66. bubbleIframeMouseMove(iframe);
  67. setTimeout(function() {
  68. const doc = iframe.contentDocument;
  69. // the iframes inside of the etherpad are
  70. // not yet loaded when the etherpad iframe is loaded
  71. const outer = doc.getElementsByName("ace_outer")[0];
  72. bubbleIframeMouseMove(outer);
  73. const inner = doc.getElementsByName("ace_inner")[0];
  74. bubbleIframeMouseMove(inner);
  75. }, 2000);
  76. };
  77. this.iframe = iframe;
  78. }
  79. get isOpen () {
  80. return !!this.iframe;
  81. }
  82. get container () {
  83. return document.getElementById('etherpad');
  84. }
  85. // eslint-disable-next-line no-unused-vars
  86. resize (containerWidth, containerHeight, animate) {
  87. let height = containerHeight - FilmStrip.getFilmStripHeight();
  88. let width = containerWidth;
  89. $(this.iframe).width(width).height(height);
  90. }
  91. show () {
  92. const $iframe = $(this.iframe);
  93. const $container = $(this.container);
  94. let self = this;
  95. return new Promise(resolve => {
  96. $iframe.fadeIn(300, function () {
  97. self.bodyBackground = document.body.style.background;
  98. document.body.style.background = '#eeeeee';
  99. $iframe.css({visibility: 'visible'});
  100. $container.css({zIndex: 2});
  101. resolve();
  102. });
  103. });
  104. }
  105. hide () {
  106. const $iframe = $(this.iframe);
  107. const $container = $(this.container);
  108. document.body.style.background = this.bodyBackground;
  109. return new Promise(resolve => {
  110. $iframe.fadeOut(300, function () {
  111. $iframe.css({visibility: 'hidden'});
  112. $container.css({zIndex: 0});
  113. resolve();
  114. });
  115. });
  116. }
  117. /**
  118. * @return {boolean} do not switch on dominant speaker event if on stage.
  119. */
  120. stayOnStage () {
  121. return true;
  122. }
  123. }
  124. /**
  125. * Manager of the Etherpad frame.
  126. */
  127. export default class EtherpadManager {
  128. constructor (domain, name, eventEmitter) {
  129. if (!domain || !name) {
  130. throw new Error("missing domain or name");
  131. }
  132. this.domain = domain;
  133. this.name = name;
  134. this.eventEmitter = eventEmitter;
  135. this.etherpad = null;
  136. }
  137. get isOpen () {
  138. return !!this.etherpad;
  139. }
  140. isVisible() {
  141. return VideoLayout.isLargeContainerTypeVisible(ETHERPAD_CONTAINER_TYPE);
  142. }
  143. /**
  144. * Create new Etherpad frame.
  145. */
  146. openEtherpad () {
  147. this.etherpad = new Etherpad(this.domain, this.name);
  148. VideoLayout.addLargeVideoContainer(
  149. ETHERPAD_CONTAINER_TYPE,
  150. this.etherpad
  151. );
  152. }
  153. /**
  154. * Toggle Etherpad frame visibility.
  155. * Open new Etherpad frame if there is no Etherpad frame yet.
  156. */
  157. toggleEtherpad () {
  158. if (!this.isOpen) {
  159. this.openEtherpad();
  160. }
  161. let isVisible = this.isVisible();
  162. VideoLayout.showLargeVideoContainer(
  163. ETHERPAD_CONTAINER_TYPE, !isVisible);
  164. this.eventEmitter
  165. .emit(UIEvents.TOGGLED_SHARED_DOCUMENT, !isVisible);
  166. }
  167. }