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.

external_api.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /**
  2. * Implements API class that embeds Jitsi Meet in external applications.
  3. */
  4. var JitsiMeetExternalAPI = (function()
  5. {
  6. /**
  7. * The minimum width for the Jitsi Meet frame
  8. * @type {number}
  9. */
  10. var MIN_WIDTH = 790;
  11. /**
  12. * The minimum height for the Jitsi Meet frame
  13. * @type {number}
  14. */
  15. var MIN_HEIGHT = 300;
  16. /**
  17. * Constructs new API instance. Creates iframe element that loads
  18. * Jitsi Meet.
  19. * @param domain the domain name of the server that hosts the conference
  20. * @param room_name the name of the room to join
  21. * @param width width of the iframe
  22. * @param height height of the iframe
  23. * @param parent_node the node that will contain the iframe
  24. * @param filmStripOnly if the value is true only the small videos will be
  25. * visible.
  26. * @constructor
  27. */
  28. function JitsiMeetExternalAPI(domain, room_name, width, height, parentNode,
  29. filmStripOnly) {
  30. if((!width || width < MIN_WIDTH) && !filmStripOnly)
  31. width = MIN_WIDTH;
  32. if((!height || height < MIN_HEIGHT) && !filmStripOnly)
  33. height = MIN_HEIGHT;
  34. this.parentNode = null;
  35. if (parentNode) {
  36. this.parentNode = parentNode;
  37. } else {
  38. var scriptTag = document.scripts[document.scripts.length - 1];
  39. this.parentNode = scriptTag.parentNode;
  40. }
  41. this.iframeHolder =
  42. this.parentNode.appendChild(document.createElement("div"));
  43. this.iframeHolder.id = "jitsiConference" + JitsiMeetExternalAPI.id;
  44. if(width)
  45. this.iframeHolder.style.width = width + "px";
  46. if(height)
  47. this.iframeHolder.style.height = height + "px";
  48. this.frameName = "jitsiConferenceFrame" + JitsiMeetExternalAPI.id;
  49. this.url = "//" + domain + "/";
  50. if(room_name)
  51. this.url += room_name;
  52. this.url += "#external=true";
  53. if(filmStripOnly)
  54. this.url += "&interfaceConfig.filmStripOnly=true";
  55. JitsiMeetExternalAPI.id++;
  56. this.frame = document.createElement("iframe");
  57. this.frame.src = this.url;
  58. this.frame.name = this.frameName;
  59. this.frame.id = this.frameName;
  60. this.frame.width = "100%";
  61. this.frame.height = "100%";
  62. this.frame.setAttribute("allowFullScreen","true");
  63. this.frame = this.iframeHolder.appendChild(this.frame);
  64. this.frameLoaded = false;
  65. this.initialCommands = [];
  66. this.eventHandlers = {};
  67. this.initListeners();
  68. }
  69. /**
  70. * Last id of api object
  71. * @type {number}
  72. */
  73. JitsiMeetExternalAPI.id = 0;
  74. /**
  75. * Sends the passed object to Jitsi Meet
  76. * @param object the object to be sent
  77. */
  78. JitsiMeetExternalAPI.prototype.sendMessage = function(object) {
  79. if (this.frameLoaded) {
  80. this.frame.contentWindow.postMessage(
  81. JSON.stringify(object), this.frame.src);
  82. }
  83. else {
  84. this.initialCommands.push(object);
  85. }
  86. };
  87. /**
  88. * Executes command. The available commands are:
  89. * displayName - sets the display name of the local participant to the value
  90. * passed in the arguments array.
  91. * toggleAudio - mutes / unmutes audio with no arguments
  92. * toggleVideo - mutes / unmutes video with no arguments
  93. * filmStrip - hides / shows the film strip with no arguments
  94. * If the command doesn't require any arguments the parameter should be set
  95. * to empty array or it may be omitted.
  96. * @param name the name of the command
  97. * @param arguments array of arguments
  98. */
  99. JitsiMeetExternalAPI.prototype.executeCommand = function(name,
  100. argumentsList) {
  101. var argumentsArray = argumentsList;
  102. if (!argumentsArray)
  103. argumentsArray = [];
  104. var object = {type: "command", action: "execute"};
  105. object[name] = argumentsArray;
  106. this.sendMessage(object);
  107. };
  108. /**
  109. * Executes commands. The available commands are:
  110. * displayName - sets the display name of the local participant to the value
  111. * passed in the arguments array.
  112. * toggleAudio - mutes / unmutes audio with no arguments
  113. * toggleVideo - mutes / unmutes video with no arguments
  114. * filmStrip - hides / shows the film strip with no arguments
  115. * @param object the object with commands to be executed. The keys of the
  116. * object are the commands that will be executed and the values are the
  117. * arguments for the command.
  118. */
  119. JitsiMeetExternalAPI.prototype.executeCommands = function (object) {
  120. object.type = "command";
  121. object.action = "execute";
  122. this.sendMessage(object);
  123. };
  124. /**
  125. * Adds event listeners to Meet Jitsi. The object key should be the name of
  126. * the event and value - the listener.
  127. * Currently we support the following
  128. * events:
  129. * incomingMessage - receives event notifications about incoming
  130. * messages. The listener will receive object with the following structure:
  131. * {{
  132. * "from": from,//JID of the user that sent the message
  133. * "nick": nick,//the nickname of the user that sent the message
  134. * "message": txt//the text of the message
  135. * }}
  136. * outgoingMessage - receives event notifications about outgoing
  137. * messages. The listener will receive object with the following structure:
  138. * {{
  139. * "message": txt//the text of the message
  140. * }}
  141. * displayNameChanged - receives event notifications about display name
  142. * change. The listener will receive object with the following structure:
  143. * {{
  144. * jid: jid,//the JID of the participant that changed his display name
  145. * displayname: displayName //the new display name
  146. * }}
  147. * participantJoined - receives event notifications about new participant.
  148. * The listener will receive object with the following structure:
  149. * {{
  150. * jid: jid //the jid of the participant
  151. * }}
  152. * participantLeft - receives event notifications about participant that left room.
  153. * The listener will receive object with the following structure:
  154. * {{
  155. * jid: jid //the jid of the participant
  156. * }}
  157. * @param object
  158. */
  159. JitsiMeetExternalAPI.prototype.addEventListeners
  160. = function (object) {
  161. var message = {type: "event", action: "add", events: []};
  162. for(var i in object)
  163. {
  164. message.events.push(i);
  165. this.eventHandlers[i] = object[i];
  166. }
  167. this.sendMessage(message);
  168. };
  169. /**
  170. * Adds event listeners to Meet Jitsi. Currently we support the following
  171. * events:
  172. * incomingMessage - receives event notifications about incoming
  173. * messages. The listener will receive object with the following structure:
  174. * {{
  175. * "from": from,//JID of the user that sent the message
  176. * "nick": nick,//the nickname of the user that sent the message
  177. * "message": txt//the text of the message
  178. * }}
  179. * outgoingMessage - receives event notifications about outgoing
  180. * messages. The listener will receive object with the following structure:
  181. * {{
  182. * "message": txt//the text of the message
  183. * }}
  184. * displayNameChanged - receives event notifications about display name
  185. * change. The listener will receive object with the following structure:
  186. * {{
  187. * jid: jid,//the JID of the participant that changed his display name
  188. * displayname: displayName //the new display name
  189. * }}
  190. * participantJoined - receives event notifications about new participant.
  191. * The listener will receive object with the following structure:
  192. * {{
  193. * jid: jid //the jid of the participant
  194. * }}
  195. * participantLeft - receives event notifications about participant that left room.
  196. * The listener will receive object with the following structure:
  197. * {{
  198. * jid: jid //the jid of the participant
  199. * }}
  200. * @param event the name of the event
  201. * @param listener the listener
  202. */
  203. JitsiMeetExternalAPI.prototype.addEventListener
  204. = function (event, listener) {
  205. var message = {type: "event", action: "add", events: [event]};
  206. this.eventHandlers[event] = listener;
  207. this.sendMessage(message);
  208. };
  209. /**
  210. * Removes event listener.
  211. * @param event the name of the event.
  212. */
  213. JitsiMeetExternalAPI.prototype.removeEventListener
  214. = function (event) {
  215. if(!this.eventHandlers[event])
  216. {
  217. console.error("The event " + event + " is not registered.");
  218. return;
  219. }
  220. var message = {type: "event", action: "remove", events: [event]};
  221. delete this.eventHandlers[event];
  222. this.sendMessage(message);
  223. };
  224. /**
  225. * Removes event listeners.
  226. * @param events array with the names of the events.
  227. */
  228. JitsiMeetExternalAPI.prototype.removeEventListeners
  229. = function (events) {
  230. var eventsArray = [];
  231. for(var i = 0; i < events.length; i++)
  232. {
  233. var event = events[i];
  234. if(!this.eventHandlers[event])
  235. {
  236. console.error("The event " + event + " is not registered.");
  237. continue;
  238. }
  239. delete this.eventHandlers[event];
  240. eventsArray.push(event);
  241. }
  242. if(eventsArray.length > 0)
  243. {
  244. this.sendMessage(
  245. {type: "event", action: "remove", events: eventsArray});
  246. }
  247. };
  248. /**
  249. * Processes message events sent from Jitsi Meet
  250. * @param event the event
  251. */
  252. JitsiMeetExternalAPI.prototype.processMessage = function(event) {
  253. var message;
  254. try {
  255. message = JSON.parse(event.data);
  256. } catch (e) {}
  257. if(!message.type) {
  258. console.error("Message without type is received.");
  259. return;
  260. }
  261. switch (message.type) {
  262. case "system":
  263. if(message.loaded) {
  264. this.onFrameLoaded();
  265. }
  266. break;
  267. case "event":
  268. if(message.action != "result" ||
  269. !message.event || !this.eventHandlers[message.event]) {
  270. console.warn("The received event cannot be parsed.");
  271. return;
  272. }
  273. this.eventHandlers[message.event](message.result);
  274. break;
  275. default :
  276. console.error("Unknown message type.");
  277. return;
  278. }
  279. };
  280. /**
  281. * That method is called when the Jitsi Meet is loaded. Executes saved
  282. * commands that are send before the frame was loaded.
  283. */
  284. JitsiMeetExternalAPI.prototype.onFrameLoaded = function () {
  285. this.frameLoaded = true;
  286. for (var i = 0; i < this.initialCommands.length; i++) {
  287. this.sendMessage(this.initialCommands[i]);
  288. }
  289. this.initialCommands = null;
  290. };
  291. /**
  292. * Setups the listener for message events from Jitsi Meet.
  293. */
  294. JitsiMeetExternalAPI.prototype.initListeners = function () {
  295. var self = this;
  296. this.eventListener = function (event) {
  297. self.processMessage(event);
  298. };
  299. if (window.addEventListener) {
  300. window.addEventListener('message',
  301. this.eventListener, false);
  302. }
  303. else {
  304. window.attachEvent('onmessage', this.eventListener);
  305. }
  306. };
  307. /**
  308. * Removes the listeners and removes the Jitsi Meet frame.
  309. */
  310. JitsiMeetExternalAPI.prototype.dispose = function () {
  311. if (window.removeEventListener) {
  312. window.removeEventListener('message',
  313. this.eventListener, false);
  314. }
  315. else {
  316. window.detachEvent('onmessage',
  317. this.eventListener);
  318. }
  319. var frame = document.getElementById(this.frameName);
  320. if(frame)
  321. frame.src = 'about:blank';
  322. var self = this;
  323. window.setTimeout(function () {
  324. self.iframeHolder.removeChild(self.frame);
  325. self.iframeHolder.parentNode.removeChild(self.iframeHolder);
  326. }, 10);
  327. };
  328. return JitsiMeetExternalAPI;
  329. })();