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

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