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.

chat.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /* global $, Util, connection, nickname:true, getVideoSize, getVideoPosition, showToolbar, processReplacements */
  2. /**
  3. * Chat related user interface.
  4. */
  5. var Chat = (function (my) {
  6. var notificationInterval = false;
  7. var unreadMessages = 0;
  8. /**
  9. * Initializes chat related interface.
  10. */
  11. my.init = function () {
  12. var storedDisplayName = window.localStorage.displayname;
  13. if (storedDisplayName) {
  14. nickname = storedDisplayName;
  15. Chat.setChatConversationMode(true);
  16. }
  17. $('#nickinput').keydown(function (event) {
  18. if (event.keyCode === 13) {
  19. event.preventDefault();
  20. var val = Util.escapeHtml(this.value);
  21. this.value = '';
  22. if (!nickname) {
  23. nickname = val;
  24. window.localStorage.displayname = nickname;
  25. connection.emuc.addDisplayNameToPresence(nickname);
  26. connection.emuc.sendPresence();
  27. Chat.setChatConversationMode(true);
  28. return;
  29. }
  30. }
  31. });
  32. $('#usermsg').keydown(function (event) {
  33. if (event.keyCode === 13) {
  34. event.preventDefault();
  35. var value = this.value;
  36. $('#usermsg').val('').trigger('autosize.resize');
  37. this.focus();
  38. var command = new CommandsProcessor(value);
  39. if(command.isCommand())
  40. {
  41. command.processCommand();
  42. }
  43. else
  44. {
  45. var message = Util.escapeHtml(value);
  46. connection.emuc.sendMessage(message, nickname);
  47. }
  48. }
  49. });
  50. var onTextAreaResize = function () {
  51. resizeChatConversation();
  52. scrollChatToBottom();
  53. };
  54. $('#usermsg').autosize({callback: onTextAreaResize});
  55. $("#chatspace").bind("shown",
  56. function () {
  57. unreadMessages = 0;
  58. setVisualNotification(false);
  59. });
  60. };
  61. /**
  62. * Appends the given message to the chat conversation.
  63. */
  64. my.updateChatConversation = function (from, displayName, message) {
  65. var divClassName = '';
  66. if (connection.emuc.myroomjid === from) {
  67. divClassName = "localuser";
  68. }
  69. else {
  70. divClassName = "remoteuser";
  71. if (!Chat.isVisible()) {
  72. unreadMessages++;
  73. Util.playSoundNotification('chatNotification');
  74. setVisualNotification(true);
  75. }
  76. }
  77. //replace links and smileys
  78. var escMessage = Util.escapeHtml(message);
  79. var escDisplayName = Util.escapeHtml(displayName);
  80. message = processReplacements(escMessage);
  81. $('#chatconversation').append('<div class="' + divClassName + '"><b>' +
  82. escDisplayName + ': </b>' +
  83. message + '</div>');
  84. $('#chatconversation').animate(
  85. { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
  86. };
  87. /**
  88. * Appends error message to the conversation
  89. * @param errorMessage the received error message.
  90. * @param originalText the original message.
  91. */
  92. my.chatAddError = function(errorMessage, originalText)
  93. {
  94. errorMessage = Util.escapeHtml(errorMessage);
  95. originalText = Util.escapeHtml(originalText);
  96. $('#chatconversation').append('<div class="errorMessage"><b>Error: </b>'
  97. + 'Your message' + (originalText? (' \"'+ originalText + '\"') : "")
  98. + ' was not sent.' + (errorMessage? (' Reason: ' + errorMessage) : '')
  99. + '</div>');
  100. $('#chatconversation').animate(
  101. { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
  102. };
  103. /**
  104. * Sets the subject to the UI
  105. * @param subject the subject
  106. */
  107. my.chatSetSubject = function(subject)
  108. {
  109. if(subject)
  110. subject = subject.trim();
  111. $('#subject').html(linkify(Util.escapeHtml(subject)));
  112. if(subject == "")
  113. {
  114. $("#subject").css({display: "none"});
  115. }
  116. else
  117. {
  118. $("#subject").css({display: "block"});
  119. }
  120. };
  121. /**
  122. * Opens / closes the chat area.
  123. */
  124. my.toggleChat = function () {
  125. var chatspace = $('#chatspace');
  126. var videospace = $('#videospace');
  127. var chatSize = (chatspace.is(":visible")) ? [0, 0] : Chat.getChatSize();
  128. var videospaceWidth = window.innerWidth - chatSize[0];
  129. var videospaceHeight = window.innerHeight;
  130. var videoSize
  131. = getVideoSize(null, null, videospaceWidth, videospaceHeight);
  132. var videoWidth = videoSize[0];
  133. var videoHeight = videoSize[1];
  134. var videoPosition = getVideoPosition(videoWidth,
  135. videoHeight,
  136. videospaceWidth,
  137. videospaceHeight);
  138. var horizontalIndent = videoPosition[0];
  139. var verticalIndent = videoPosition[1];
  140. var thumbnailSize = VideoLayout.calculateThumbnailSize(videospaceWidth);
  141. var thumbnailsWidth = thumbnailSize[0];
  142. var thumbnailsHeight = thumbnailSize[1];
  143. if (chatspace.is(":visible")) {
  144. videospace.animate({right: chatSize[0],
  145. width: videospaceWidth,
  146. height: videospaceHeight},
  147. {queue: false,
  148. duration: 500});
  149. $('#remoteVideos').animate({height: thumbnailsHeight},
  150. {queue: false,
  151. duration: 500});
  152. $('#remoteVideos>span').animate({height: thumbnailsHeight,
  153. width: thumbnailsWidth},
  154. {queue: false,
  155. duration: 500,
  156. complete: function() {
  157. $(document).trigger(
  158. "remotevideo.resized",
  159. [thumbnailsWidth,
  160. thumbnailsHeight]);
  161. }});
  162. $('#largeVideoContainer').animate({ width: videospaceWidth,
  163. height: videospaceHeight},
  164. {queue: false,
  165. duration: 500
  166. });
  167. $('#largeVideo').animate({ width: videoWidth,
  168. height: videoHeight,
  169. top: verticalIndent,
  170. bottom: verticalIndent,
  171. left: horizontalIndent,
  172. right: horizontalIndent},
  173. { queue: false,
  174. duration: 500
  175. });
  176. $('#chatspace').hide("slide", { direction: "right",
  177. queue: false,
  178. duration: 500});
  179. }
  180. else {
  181. // Undock the toolbar when the chat is shown and if we're in a
  182. // video mode.
  183. if (VideoLayout.isLargeVideoVisible())
  184. ToolbarToggler.dockToolbar(false);
  185. videospace.animate({right: chatSize[0],
  186. width: videospaceWidth,
  187. height: videospaceHeight},
  188. {queue: false,
  189. duration: 500,
  190. complete: function () {
  191. scrollChatToBottom();
  192. chatspace.trigger('shown');
  193. }
  194. });
  195. $('#remoteVideos').animate({height: thumbnailsHeight},
  196. {queue: false,
  197. duration: 500});
  198. $('#remoteVideos>span').animate({height: thumbnailsHeight,
  199. width: thumbnailsWidth},
  200. {queue: false,
  201. duration: 500,
  202. complete: function() {
  203. $(document).trigger(
  204. "remotevideo.resized",
  205. [thumbnailsWidth, thumbnailsHeight]);
  206. }});
  207. $('#largeVideoContainer').animate({ width: videospaceWidth,
  208. height: videospaceHeight},
  209. {queue: false,
  210. duration: 500
  211. });
  212. $('#largeVideo').animate({ width: videoWidth,
  213. height: videoHeight,
  214. top: verticalIndent,
  215. bottom: verticalIndent,
  216. left: horizontalIndent,
  217. right: horizontalIndent},
  218. {queue: false,
  219. duration: 500
  220. });
  221. $('#chatspace').show("slide", { direction: "right",
  222. queue: false,
  223. duration: 500,
  224. complete: function () {
  225. // Request the focus in the nickname field or the chat input field.
  226. if ($('#nickname').css('visibility') === 'visible') {
  227. $('#nickinput').focus();
  228. } else {
  229. $('#usermsg').focus();
  230. }
  231. }
  232. });
  233. }
  234. };
  235. /**
  236. * Sets the chat conversation mode.
  237. */
  238. my.setChatConversationMode = function (isConversationMode) {
  239. if (isConversationMode) {
  240. $('#nickname').css({visibility: 'hidden'});
  241. $('#chatconversation').css({visibility: 'visible'});
  242. $('#usermsg').css({visibility: 'visible'});
  243. $('#usermsg').focus();
  244. }
  245. };
  246. /**
  247. * Resizes the chat area.
  248. */
  249. my.resizeChat = function () {
  250. var chatSize = Chat.getChatSize();
  251. $('#chatspace').width(chatSize[0]);
  252. $('#chatspace').height(chatSize[1]);
  253. resizeChatConversation();
  254. };
  255. /**
  256. * Returns the size of the chat.
  257. */
  258. my.getChatSize = function () {
  259. var availableHeight = window.innerHeight;
  260. var availableWidth = window.innerWidth;
  261. var chatWidth = 200;
  262. if (availableWidth * 0.2 < 200)
  263. chatWidth = availableWidth * 0.2;
  264. return [chatWidth, availableHeight];
  265. };
  266. /**
  267. * Indicates if the chat is currently visible.
  268. */
  269. my.isVisible = function () {
  270. return $('#chatspace').is(":visible");
  271. };
  272. /**
  273. * Resizes the chat conversation.
  274. */
  275. function resizeChatConversation() {
  276. var usermsgStyleHeight = document.getElementById("usermsg").style.height;
  277. var usermsgHeight = usermsgStyleHeight
  278. .substring(0, usermsgStyleHeight.indexOf('px'));
  279. $('#usermsg').width($('#chatspace').width() - 10);
  280. $('#chatconversation').width($('#chatspace').width() - 10);
  281. $('#chatconversation')
  282. .height(window.innerHeight - 10 - parseInt(usermsgHeight));
  283. }
  284. /**
  285. * Shows/hides a visual notification, indicating that a message has arrived.
  286. */
  287. function setVisualNotification(show) {
  288. var unreadMsgElement = document.getElementById('unreadMessages');
  289. var glower = $('#chatButton');
  290. if (unreadMessages) {
  291. unreadMsgElement.innerHTML = unreadMessages.toString();
  292. ToolbarToggler.dockToolbar(true);
  293. var chatButtonElement
  294. = document.getElementById('chatButton').parentNode;
  295. var leftIndent = (Util.getTextWidth(chatButtonElement) -
  296. Util.getTextWidth(unreadMsgElement)) / 2;
  297. var topIndent = (Util.getTextHeight(chatButtonElement) -
  298. Util.getTextHeight(unreadMsgElement)) / 2 - 3;
  299. unreadMsgElement.setAttribute(
  300. 'style',
  301. 'top:' + topIndent +
  302. '; left:' + leftIndent + ';');
  303. if (!glower.hasClass('icon-chat-simple')) {
  304. glower.removeClass('icon-chat');
  305. glower.addClass('icon-chat-simple');
  306. }
  307. }
  308. else {
  309. unreadMsgElement.innerHTML = '';
  310. glower.removeClass('icon-chat-simple');
  311. glower.addClass('icon-chat');
  312. }
  313. if (show && !notificationInterval) {
  314. notificationInterval = window.setInterval(function () {
  315. glower.toggleClass('active');
  316. }, 800);
  317. }
  318. else if (!show && notificationInterval) {
  319. window.clearInterval(notificationInterval);
  320. notificationInterval = false;
  321. glower.removeClass('active');
  322. }
  323. }
  324. /**
  325. * Scrolls chat to the bottom.
  326. */
  327. function scrollChatToBottom() {
  328. setTimeout(function () {
  329. $('#chatconversation').scrollTop(
  330. $('#chatconversation')[0].scrollHeight);
  331. }, 5);
  332. }
  333. return my;
  334. }(Chat || {}));