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

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