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 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /* global $, Util, connection, nickname:true, showToolbar */
  2. var Replacement = require("./Replacement");
  3. var CommandsProcessor = require("./Commands");
  4. var ToolbarToggler = require("../../toolbars/ToolbarToggler");
  5. var smileys = require("./smileys.json").smileys;
  6. var notificationInterval = false;
  7. var unreadMessages = 0;
  8. /**
  9. * Shows/hides a visual notification, indicating that a message has arrived.
  10. */
  11. function setVisualNotification(show) {
  12. var unreadMsgElement = document.getElementById('unreadMessages');
  13. var unreadMsgBottomElement
  14. = document.getElementById('bottomUnreadMessages');
  15. var glower = $('#chatButton');
  16. var bottomGlower = $('#chatBottomButton');
  17. if (unreadMessages) {
  18. unreadMsgElement.innerHTML = unreadMessages.toString();
  19. unreadMsgBottomElement.innerHTML = unreadMessages.toString();
  20. ToolbarToggler.dockToolbar(true);
  21. var chatButtonElement
  22. = document.getElementById('chatButton').parentNode;
  23. var leftIndent = (Util.getTextWidth(chatButtonElement) -
  24. Util.getTextWidth(unreadMsgElement)) / 2;
  25. var topIndent = (Util.getTextHeight(chatButtonElement) -
  26. Util.getTextHeight(unreadMsgElement)) / 2 - 3;
  27. unreadMsgElement.setAttribute(
  28. 'style',
  29. 'top:' + topIndent +
  30. '; left:' + leftIndent + ';');
  31. var chatBottomButtonElement
  32. = document.getElementById('chatBottomButton').parentNode;
  33. var bottomLeftIndent = (Util.getTextWidth(chatBottomButtonElement) -
  34. Util.getTextWidth(unreadMsgBottomElement)) / 2;
  35. var bottomTopIndent = (Util.getTextHeight(chatBottomButtonElement) -
  36. Util.getTextHeight(unreadMsgBottomElement)) / 2 - 2;
  37. unreadMsgBottomElement.setAttribute(
  38. 'style',
  39. 'top:' + bottomTopIndent +
  40. '; left:' + bottomLeftIndent + ';');
  41. if (!glower.hasClass('icon-chat-simple')) {
  42. glower.removeClass('icon-chat');
  43. glower.addClass('icon-chat-simple');
  44. }
  45. }
  46. else {
  47. unreadMsgElement.innerHTML = '';
  48. unreadMsgBottomElement.innerHTML = '';
  49. glower.removeClass('icon-chat-simple');
  50. glower.addClass('icon-chat');
  51. }
  52. if (show && !notificationInterval) {
  53. notificationInterval = window.setInterval(function () {
  54. glower.toggleClass('active');
  55. bottomGlower.toggleClass('active glowing');
  56. }, 800);
  57. }
  58. else if (!show && notificationInterval) {
  59. window.clearInterval(notificationInterval);
  60. notificationInterval = false;
  61. glower.removeClass('active');
  62. bottomGlower.removeClass('glowing');
  63. bottomGlower.addClass('active');
  64. }
  65. }
  66. /**
  67. * Returns the current time in the format it is shown to the user
  68. * @returns {string}
  69. */
  70. function getCurrentTime() {
  71. var now = new Date();
  72. var hour = now.getHours();
  73. var minute = now.getMinutes();
  74. var second = now.getSeconds();
  75. if(hour.toString().length === 1) {
  76. hour = '0'+hour;
  77. }
  78. if(minute.toString().length === 1) {
  79. minute = '0'+minute;
  80. }
  81. if(second.toString().length === 1) {
  82. second = '0'+second;
  83. }
  84. return hour+':'+minute+':'+second;
  85. }
  86. function toggleSmileys()
  87. {
  88. var smileys = $('#smileysContainer');
  89. if(!smileys.is(':visible')) {
  90. smileys.show("slide", { direction: "down", duration: 300});
  91. } else {
  92. smileys.hide("slide", { direction: "down", duration: 300});
  93. }
  94. $('#usermsg').focus();
  95. }
  96. function addClickFunction(smiley, number) {
  97. smiley.onclick = function addSmileyToMessage() {
  98. var usermsg = $('#usermsg');
  99. var message = usermsg.val();
  100. message += smileys['smiley' + number];
  101. usermsg.val(message);
  102. usermsg.get(0).setSelectionRange(message.length, message.length);
  103. toggleSmileys();
  104. usermsg.focus();
  105. };
  106. }
  107. /**
  108. * Adds the smileys container to the chat
  109. */
  110. function addSmileys() {
  111. var smileysContainer = document.createElement('div');
  112. smileysContainer.id = 'smileysContainer';
  113. for(var i = 1; i <= 21; i++) {
  114. var smileyContainer = document.createElement('div');
  115. smileyContainer.id = 'smiley' + i;
  116. smileyContainer.className = 'smileyContainer';
  117. var smiley = document.createElement('img');
  118. smiley.src = 'images/smileys/smiley' + i + '.svg';
  119. smiley.className = 'smiley';
  120. addClickFunction(smiley, i);
  121. smileyContainer.appendChild(smiley);
  122. smileysContainer.appendChild(smileyContainer);
  123. }
  124. $("#chatspace").append(smileysContainer);
  125. }
  126. /**
  127. * Resizes the chat conversation.
  128. */
  129. function resizeChatConversation() {
  130. var msgareaHeight = $('#usermsg').outerHeight();
  131. var chatspace = $('#chatspace');
  132. var width = chatspace.width();
  133. var chat = $('#chatconversation');
  134. var smileys = $('#smileysarea');
  135. smileys.height(msgareaHeight);
  136. $("#smileys").css('bottom', (msgareaHeight - 26) / 2);
  137. $('#smileysContainer').css('bottom', msgareaHeight);
  138. chat.width(width - 10);
  139. chat.height(window.innerHeight - 15 - msgareaHeight);
  140. }
  141. /**
  142. * Chat related user interface.
  143. */
  144. var Chat = (function (my) {
  145. /**
  146. * Initializes chat related interface.
  147. */
  148. my.init = function () {
  149. var storedDisplayName = window.localStorage.displayname;
  150. if (storedDisplayName) {
  151. nickname = storedDisplayName;
  152. Chat.setChatConversationMode(true);
  153. }
  154. $('#nickinput').keydown(function (event) {
  155. if (event.keyCode === 13) {
  156. event.preventDefault();
  157. var val = Util.escapeHtml(this.value);
  158. this.value = '';
  159. if (!nickname) {
  160. nickname = val;
  161. window.localStorage.displayname = nickname;
  162. connection.emuc.addDisplayNameToPresence(nickname);
  163. connection.emuc.sendPresence();
  164. Chat.setChatConversationMode(true);
  165. return;
  166. }
  167. }
  168. });
  169. $('#usermsg').keydown(function (event) {
  170. if (event.keyCode === 13) {
  171. event.preventDefault();
  172. var value = this.value;
  173. $('#usermsg').val('').trigger('autosize.resize');
  174. this.focus();
  175. var command = new CommandsProcessor(value);
  176. if(command.isCommand())
  177. {
  178. command.processCommand();
  179. }
  180. else
  181. {
  182. var message = Util.escapeHtml(value);
  183. connection.emuc.sendMessage(message, nickname);
  184. }
  185. }
  186. });
  187. var onTextAreaResize = function () {
  188. resizeChatConversation();
  189. Chat.scrollChatToBottom();
  190. };
  191. $('#usermsg').autosize({callback: onTextAreaResize});
  192. $("#chatspace").bind("shown",
  193. function () {
  194. unreadMessages = 0;
  195. setVisualNotification(false);
  196. });
  197. addSmileys();
  198. };
  199. /**
  200. * Appends the given message to the chat conversation.
  201. */
  202. my.updateChatConversation = function (from, displayName, message) {
  203. var divClassName = '';
  204. if (connection.emuc.myroomjid === from) {
  205. divClassName = "localuser";
  206. }
  207. else {
  208. divClassName = "remoteuser";
  209. if (!Chat.isVisible()) {
  210. unreadMessages++;
  211. Util.playSoundNotification('chatNotification');
  212. setVisualNotification(true);
  213. }
  214. }
  215. // replace links and smileys
  216. // Strophe already escapes special symbols on sending,
  217. // so we escape here only tags to avoid double &amp;
  218. var escMessage = message.replace(/</g, '&lt;').
  219. replace(/>/g, '&gt;').replace(/\n/g, '<br/>');
  220. var escDisplayName = Util.escapeHtml(displayName);
  221. message = Replacement.processReplacements(escMessage);
  222. var messageContainer =
  223. '<div class="chatmessage">'+
  224. '<img src="../images/chatArrow.svg" class="chatArrow">' +
  225. '<div class="username ' + divClassName +'">' + escDisplayName +
  226. '</div>' + '<div class="timestamp">' + getCurrentTime() +
  227. '</div>' + '<div class="usermessage">' + message + '</div>' +
  228. '</div>';
  229. $('#chatconversation').append(messageContainer);
  230. $('#chatconversation').animate(
  231. { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
  232. };
  233. /**
  234. * Appends error message to the conversation
  235. * @param errorMessage the received error message.
  236. * @param originalText the original message.
  237. */
  238. my.chatAddError = function(errorMessage, originalText)
  239. {
  240. errorMessage = Util.escapeHtml(errorMessage);
  241. originalText = Util.escapeHtml(originalText);
  242. $('#chatconversation').append(
  243. '<div class="errorMessage"><b>Error: </b>' + 'Your message' +
  244. (originalText? (' \"'+ originalText + '\"') : "") +
  245. ' was not sent.' +
  246. (errorMessage? (' Reason: ' + errorMessage) : '') + '</div>');
  247. $('#chatconversation').animate(
  248. { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
  249. };
  250. /**
  251. * Sets the subject to the UI
  252. * @param subject the subject
  253. */
  254. my.chatSetSubject = function(subject)
  255. {
  256. if(subject)
  257. subject = subject.trim();
  258. $('#subject').html(Replacement.linkify(Util.escapeHtml(subject)));
  259. if(subject === "")
  260. {
  261. $("#subject").css({display: "none"});
  262. }
  263. else
  264. {
  265. $("#subject").css({display: "block"});
  266. }
  267. };
  268. /**
  269. * Sets the chat conversation mode.
  270. */
  271. my.setChatConversationMode = function (isConversationMode) {
  272. if (isConversationMode) {
  273. $('#nickname').css({visibility: 'hidden'});
  274. $('#chatconversation').css({visibility: 'visible'});
  275. $('#usermsg').css({visibility: 'visible'});
  276. $('#smileysarea').css({visibility: 'visible'});
  277. $('#usermsg').focus();
  278. }
  279. };
  280. /**
  281. * Resizes the chat area.
  282. */
  283. my.resizeChat = function () {
  284. var chatSize = require("../SidePanelToggler").getPanelSize();
  285. $('#chatspace').width(chatSize[0]);
  286. $('#chatspace').height(chatSize[1]);
  287. resizeChatConversation();
  288. };
  289. /**
  290. * Indicates if the chat is currently visible.
  291. */
  292. my.isVisible = function () {
  293. return $('#chatspace').is(":visible");
  294. };
  295. /**
  296. * Shows and hides the window with the smileys
  297. */
  298. my.toggleSmileys = toggleSmileys;
  299. /**
  300. * Scrolls chat to the bottom.
  301. */
  302. my.scrollChatToBottom = function() {
  303. setTimeout(function () {
  304. $('#chatconversation').scrollTop(
  305. $('#chatconversation')[0].scrollHeight);
  306. }, 5);
  307. };
  308. return my;
  309. }(Chat || {}));
  310. module.exports = Chat;