chat.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /*
  2. Copyright (c) 2009 Anant Garg (anantgarg.com | inscripts.com)
  3. This script may be used for non-commercial purposes only. For any
  4. commercial purposes, please contact the author at
  5. anant.garg@inscripts.com
  6. Changes and Chamilo Integration: Julio Montoya <gugli100@gmail.com>
  7. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  8. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  9. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  10. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  11. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  12. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  13. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  14. OTHER DEALINGS IN THE SOFTWARE.
  15. */
  16. var windowFocus = true;
  17. var username;
  18. var chatHeartbeatCount = 0;
  19. var minChatHeartbeat = 4000;
  20. var maxChatHeartbeat = 33000;
  21. var chatHeartbeatTime = minChatHeartbeat;
  22. var originalTitle;
  23. var blinkOrder = 0;
  24. var chatboxFocus = new Array();
  25. var newMessages = new Array();
  26. var newMessagesWin = new Array();
  27. var chatBoxes = new Array();
  28. var timer;
  29. var user_status = 0;
  30. //var ajax_url = 'chat.php'; // This variable is loaded in the template/layout/head.tpl file
  31. function set_user_status(status) {
  32. $.ajax({
  33. url: ajax_url+"?action=set_status",
  34. data: "status="+status,
  35. cache: false,
  36. success: function(data) {
  37. }
  38. });
  39. user_status = status;
  40. }
  41. $(document).ready(function() {
  42. originalTitle = document.title;
  43. startChatSession();
  44. $([window, document]).blur(function() {
  45. windowFocus = false;
  46. }).focus(function(){
  47. windowFocus = true;
  48. document.title = originalTitle;
  49. });
  50. /* Live conditions */
  51. // User name header toogle
  52. $('#chatboxtitlemain').live('click', function() {
  53. if (user_status == 1) {
  54. stopChatHeartBeat();
  55. $('.user_status_main').html(offline_button);
  56. $('#chatboxtitlemain').html(disconnect_lang);
  57. set_user_status(0);
  58. } else {
  59. startChatHeartBeat();
  60. $('.user_status_main').html(online_button);
  61. $('#chatboxtitlemain').html(connect_lang);
  62. set_user_status(1);
  63. }
  64. });
  65. // User name header toogle
  66. $('.chatboxtitle').live('click', function(){
  67. chatbox = $(this).parents(".chatbox");
  68. var chat_id = chatbox.attr('id');
  69. chat_id = chat_id.split('_')[1];
  70. toggleChatBoxGrowth(chat_id);
  71. });
  72. //Minimize button
  73. $('.chatboxhead .togglelink').live('click', function(){
  74. var chat_id = $(this).attr('rel');
  75. toggleChatBoxGrowth(chat_id);
  76. });
  77. //Close button
  78. $('.chatboxhead .closelink').live('click', function(){
  79. var chat_id = $(this).attr('rel');
  80. closeChatBox(chat_id);
  81. });
  82. });
  83. function showChatConnect() {
  84. if (user_status == 1) {
  85. button = online_button;
  86. label = connect_lang;
  87. } else {
  88. button = offline_button;
  89. label = disconnect_lang;
  90. }
  91. $("<div />" ).attr("id","chatmain")
  92. .addClass("chatboxmain")
  93. .html('<div class="chatboxheadmain"><div class="user_status_main">'+button+'</div><div id="chatboxtitlemain">'+label+'</div><div class="chatboxoptions"></div><br clear="all"/></div></div>')
  94. .appendTo($( "body" ));
  95. }
  96. /**
  97. * Start chat session
  98. */
  99. function startChatSession() {
  100. /* fix bug BT#5728 whereby users cannot move to the next question in IE9 */
  101. if (typeof ajax_url != 'undefined') {
  102. $.ajax({
  103. url: ajax_url+"?action=startchatsession",
  104. cache: false,
  105. dataType: "json",
  106. success: function(data) {
  107. if (data) {
  108. username = data.me;
  109. user_status = data.user_status;
  110. showChatConnect();
  111. if (user_status == 1) {
  112. startChatHeartBeat();
  113. } else {
  114. stopChatHeartBeat();
  115. }
  116. $.each(data.items, function(my_user_id, user_items) {
  117. my_items = user_items['items'];
  118. $.each(my_items, function(i, item) {
  119. if (item) { // fix strange ie bug
  120. //my_user_id = item.f;
  121. if ($("#chatbox_"+my_user_id).length <= 0) {
  122. createChatBox(my_user_id, user_items.user_info.user_name, 1, user_items.user_info.online);
  123. }
  124. if (item.s == 1) {
  125. //item.f = username;
  126. }
  127. if (item.s == 2) {
  128. $("#chatbox_"+my_user_id+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxinfo">'+item.m+'</span></div>');
  129. } else {
  130. $("#chatbox_"+my_user_id+" .chatboxcontent").append('<div class="chatboxmessage">\n\
  131. <span class="chatboxmessagefrom">'+item.username+':&nbsp;&nbsp;</span>\n\
  132. <span class="chatboxmessagecontent">'+item.m+'</span></div>');
  133. }
  134. }
  135. });
  136. });
  137. for (i=0;i<chatBoxes.length;i++) {
  138. my_user_id = chatBoxes[i];
  139. $("#chatbox_"+my_user_id+" .chatboxcontent").scrollTop($("#chatbox_"+my_user_id+" .chatboxcontent")[0].scrollHeight);
  140. }
  141. }
  142. }});
  143. }
  144. }
  145. function stopChatHeartBeat() {
  146. clearInterval(timer);
  147. timer = null;
  148. }
  149. function startChatHeartBeat() {
  150. timer = setInterval('chatHeartbeat();', chatHeartbeatTime);
  151. }
  152. /*
  153. * Shows the user messages in all windows
  154. *
  155. * Item array structure :
  156. *
  157. * item.s = type of message: 1 = message, 2 = "sent at" string
  158. * item.m = message
  159. * item.f = from_user
  160. *
  161. **/
  162. function chatHeartbeat() {
  163. var itemsfound = 0;
  164. if (windowFocus == false) {
  165. var blinkNumber = 0;
  166. var titleChanged = 0;
  167. for (x in newMessagesWin) {
  168. if (newMessagesWin[x].status == true) {
  169. ++blinkNumber;
  170. if (blinkNumber >= blinkOrder) {
  171. document.title = newMessagesWin[x].username+' says...';
  172. titleChanged = 1;
  173. break;
  174. }
  175. }
  176. }
  177. if (titleChanged == 0) {
  178. document.title = originalTitle;
  179. blinkOrder = 0;
  180. } else {
  181. ++blinkOrder;
  182. }
  183. } else {
  184. for (x in newMessagesWin) {
  185. newMessagesWin[x].status = false;
  186. }
  187. }
  188. for (x in newMessages) {
  189. if (newMessages[x] == true) {
  190. if (chatboxFocus[x] == false) {
  191. //FIXME: add toggle all or none policy, otherwise it looks funny
  192. $('#chatbox_'+x+' .chatboxhead').toggleClass('chatboxblink');
  193. }
  194. }
  195. }
  196. $.ajax({
  197. url: ajax_url+"?action=chatheartbeat",
  198. cache: false,
  199. dataType: "json",
  200. success: function(data) {
  201. $.each(data.items, function(my_user_id, user_items) {
  202. my_items = user_items['items'];
  203. $.each(my_items, function(i, item) {
  204. if (item) { // fix strange ie bug
  205. if ($("#chatbox_"+my_user_id).length <= 0) {
  206. createChatBox(my_user_id, user_items.user_info.user_name, 0, user_items.user_info.online);
  207. }
  208. if ($("#chatbox_"+my_user_id).css('display') == 'none') {
  209. $("#chatbox_"+my_user_id).css('display','block');
  210. restructureChatBoxes();
  211. }
  212. if (item.s == 1) {
  213. //item.f = username;
  214. }
  215. update_online_user(my_user_id, user_items.user_info.online);
  216. if (item.s == 2) {
  217. $("#chatbox_"+my_user_id+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxinfo">'+item.m+'</span></div>');
  218. } else {
  219. newMessages[my_user_id] = {'status':true, 'username':item.username};
  220. newMessagesWin[my_user_id] = {'status':true, 'username':item.username};
  221. $("#chatbox_"+my_user_id+" .chatboxcontent").append('<div class="chatboxmessage">\n\
  222. <span class="chatboxmessagefrom">'+item.username+':&nbsp;&nbsp;</span>\n\
  223. <span class="chatboxmessagecontent">'+item.m+'</span></div>');
  224. }
  225. $("#chatbox_"+my_user_id+" .chatboxcontent").scrollTop($("#chatbox_"+my_user_id+" .chatboxcontent")[0].scrollHeight);
  226. if ($('#chatbox_'+my_user_id+' .chatboxcontent').css('display') == 'none') {
  227. $('#chatbox_'+my_user_id+' .chatboxhead').toggleClass('chatboxblink');
  228. }
  229. itemsfound += 1;
  230. }
  231. });
  232. });
  233. chatHeartbeatCount++;
  234. if (itemsfound > 0) {
  235. chatHeartbeatTime = minChatHeartbeat;
  236. chatHeartbeatCount = 1;
  237. } else if (chatHeartbeatCount >= 10) {
  238. chatHeartbeatTime *= 2;
  239. chatHeartbeatCount = 1;
  240. if (chatHeartbeatTime > maxChatHeartbeat) {
  241. chatHeartbeatTime = maxChatHeartbeat;
  242. }
  243. }
  244. //timer = setTimeout('chatHeartbeat();',chatHeartbeatTime);
  245. }
  246. }); //ajax
  247. }
  248. function closeChatBox(user_id) {
  249. $('#chatbox_'+user_id).css('display','none');
  250. restructureChatBoxes();
  251. $.post(ajax_url+"?action=closechat", {chatbox: user_id} , function(data){
  252. });
  253. }
  254. function restructureChatBoxes() {
  255. align = 0;
  256. for (x in chatBoxes) {
  257. user_id = chatBoxes[x];
  258. if ($("#chatbox_"+user_id).css('display') != 'none') {
  259. if (align == 0) {
  260. $("#chatbox_"+user_id).css('right', '245px');
  261. } else {
  262. width = (align)*(225+7)+20 + 225;
  263. $("#chatbox_"+user_id).css('right', width+'px');
  264. }
  265. align++;
  266. }
  267. }
  268. }
  269. /**
  270. * Function that fires the chat with an user (creates a chat bloclk)
  271. * @param int user id
  272. * @param string user's firstname + lastname
  273. * @param status
  274. *
  275. **/
  276. function chatWith(user_id, user_name, status) {
  277. createChatBox(user_id, user_name, 0, status);
  278. $("#chatbox_"+user_id+" .chatboxtextarea").focus();
  279. }
  280. function chatNotYetWith(message) {
  281. $("#message_ajax_reponse").html(message);
  282. $("#message_ajax_reponse").css('display', 'block');
  283. $("#message_ajax_reponse").attr('class', 'alert');
  284. $('#message_ajax_reponse').alert()
  285. }
  286. /**
  287. * Creates a div
  288. */
  289. function createChatBox(user_id, chatboxtitle, minimizeChatBox, online) {
  290. if ($("#chatbox_"+user_id).length > 0) {
  291. if ($("#chatbox_"+user_id).css('display') == 'none') {
  292. $("#chatbox_"+user_id).css('display','block');
  293. restructureChatBoxes();
  294. }
  295. $("#chatbox_"+user_id+" .chatboxtextarea").focus();
  296. return;
  297. }
  298. user_is_online = return_online_user(user_id, online);
  299. $("<div />" ).attr("id","chatbox_"+user_id)
  300. .addClass("chatbox")
  301. .html('<div class="chatboxhead">\n\
  302. '+user_is_online+' \n\
  303. <div class="chatboxtitle">'+chatboxtitle+'</div>\n\
  304. <div class="chatboxoptions">\n\
  305. <a class="togglelink" rel="'+user_id+'" href="javascript:void(0)" > _ </a>&nbsp;\n\
  306. <a class="closelink" rel="'+user_id+'" href="javascript:void(0)">X</a></div>\n\
  307. <br clear="all"/></div>\n\
  308. <div class="chatboxcontent"></div>\n\
  309. <div class="chatboxinput"><textarea class="chatboxtextarea" onkeydown="javascript:return checkChatBoxInputKey(event,this,\''+user_id+'\');"></textarea></div>')
  310. .appendTo($( "body" ));
  311. $("#chatbox_"+user_id).css('bottom', '0px');
  312. chatBoxeslength = 0;
  313. for (x in chatBoxes) {
  314. if ($("#chatbox_"+chatBoxes[x]).css('display') != 'none') {
  315. chatBoxeslength++;
  316. }
  317. }
  318. if (chatBoxeslength == 0) {
  319. $("#chatbox_"+user_id).css('right', '245px');
  320. } else {
  321. width = (chatBoxeslength)*(225+7)+20 +225;
  322. $("#chatbox_"+user_id).css('right', width+'px');
  323. }
  324. chatBoxes.push(user_id);
  325. if (minimizeChatBox == 1) {
  326. minimizedChatBoxes = new Array();
  327. if ($.cookie('chatbox_minimized')) {
  328. minimizedChatBoxes = $.cookie('chatbox_minimized').split(/\|/);
  329. }
  330. minimize = 0;
  331. for (j=0;j<minimizedChatBoxes.length;j++) {
  332. if (minimizedChatBoxes[j] == user_id) {
  333. minimize = 1;
  334. }
  335. }
  336. if (minimize == 1) {
  337. $('#chatbox_'+user_id+' .chatboxcontent').css('display','none');
  338. $('#chatbox_'+user_id+' .chatboxinput').css('display','none');
  339. }
  340. }
  341. chatboxFocus[user_id] = false;
  342. $("#chatbox_"+user_id+" .chatboxtextarea").blur(function(){
  343. chatboxFocus[user_id] = false;
  344. $("#chatbox_"+user_id+" .chatboxtextarea").removeClass('chatboxtextareaselected');
  345. }).focus(function(){
  346. chatboxFocus[user_id] = true;
  347. newMessages[user_id] = false;
  348. $('#chatbox_'+user_id+' .chatboxhead').removeClass('chatboxblink');
  349. $("#chatbox_"+user_id+" .chatboxtextarea").addClass('chatboxtextareaselected');
  350. });
  351. $("#chatbox_"+user_id).click(function() {
  352. if ($('#chatbox_'+user_id+' .chatboxcontent').css('display') != 'none') {
  353. $("#chatbox_"+user_id+" .chatboxtextarea").focus();
  354. }
  355. });
  356. $("#chatbox_"+user_id).show();
  357. }
  358. /**
  359. * Creates the div user status (green/gray button next to the user name)
  360. * @param int user id
  361. * @param int status 1 or 0
  362. */
  363. function return_online_user(user_id, status) {
  364. var div_wrapper = $("<div />" );
  365. var new_div = $("<div />" );
  366. new_div.attr("id","online_"+user_id);
  367. new_div.attr("class","user_status");
  368. if (status == '1' || status == 1) {
  369. new_div.html(online_button);
  370. } else {
  371. new_div.html(offline_button);
  372. }
  373. div_wrapper.append(new_div);
  374. return div_wrapper.html();
  375. }
  376. /**
  377. * Updates the user status (green/gray button next to the user name)
  378. */
  379. function update_online_user(user_id, status) {
  380. if ($("#online_" +user_id).length > 0) {
  381. if (status == 1) {
  382. $("#online_" +user_id).html(online_button);
  383. } else {
  384. $("#online_" +user_id).html(offline_button);
  385. }
  386. }
  387. }
  388. function toggleChatBoxGrowth(user_id) {
  389. if ($('#chatbox_'+user_id+' .chatboxcontent').css('display') == 'none') {
  390. var minimizedChatBoxes = new Array();
  391. if ($.cookie('chatbox_minimized')) {
  392. minimizedChatBoxes = $.cookie('chatbox_minimized').split(/\|/);
  393. }
  394. var newCookie = '';
  395. for (i=0;i<minimizedChatBoxes.length;i++) {
  396. if (minimizedChatBoxes[i] != user_id) {
  397. newCookie += user_id+'|';
  398. }
  399. }
  400. newCookie = newCookie.slice(0, -1);
  401. $.cookie('chatbox_minimized', newCookie);
  402. $('#chatbox_'+user_id+' .chatboxcontent').css('display','block');
  403. $('#chatbox_'+user_id+' .chatboxinput').css('display','block');
  404. $("#chatbox_"+user_id+" .chatboxcontent").scrollTop($("#chatbox_"+user_id+" .chatboxcontent")[0].scrollHeight);
  405. } else {
  406. var newCookie = user_id;
  407. if ($.cookie('chatbox_minimized')) {
  408. newCookie += '|'+$.cookie('chatbox_minimized');
  409. }
  410. $.cookie('chatbox_minimized',newCookie);
  411. $('#chatbox_'+user_id+' .chatboxcontent').css('display','none');
  412. $('#chatbox_'+user_id+' .chatboxinput').css('display','none');
  413. }
  414. }
  415. function checkChatBoxInputKey(event, chatboxtextarea, user_id) {
  416. if(event.keyCode == 13 && event.shiftKey == 0) {
  417. message = $(chatboxtextarea).val();
  418. message = message.replace(/^\s+|\s+$/g,"");
  419. $(chatboxtextarea).val('');
  420. $(chatboxtextarea).focus();
  421. $(chatboxtextarea).css('height','44px');
  422. if (message != '') {
  423. $.post(ajax_url + "?action=sendchat", {to: user_id, message: message} , function(data) {
  424. message = message.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;");
  425. $("#chatbox_"+user_id+" .chatboxcontent").append('<div class="chatboxmessage">\n\
  426. <span class="chatboxmessagefrom">'+username+':&nbsp;&nbsp;</span>\n\
  427. <span class="chatboxmessagecontent">'+message+'</span></div>');
  428. $("#chatbox_"+user_id+" .chatboxcontent").scrollTop($("#chatbox_"+user_id+" .chatboxcontent")[0].scrollHeight);
  429. });
  430. }
  431. chatHeartbeatTime = minChatHeartbeat;
  432. chatHeartbeatCount = 1;
  433. return false;
  434. }
  435. var adjustedHeight = chatboxtextarea.clientHeight;
  436. var maxHeight = 94;
  437. if (maxHeight > adjustedHeight) {
  438. adjustedHeight = Math.max(chatboxtextarea.scrollHeight, adjustedHeight);
  439. if (maxHeight)
  440. adjustedHeight = Math.min(maxHeight, adjustedHeight);
  441. if (adjustedHeight > chatboxtextarea.clientHeight)
  442. $(chatboxtextarea).css('height',adjustedHeight+8 +'px');
  443. } else {
  444. $(chatboxtextarea).css('overflow','auto');
  445. }
  446. }
  447. /**
  448. * Cookie plugin
  449. *
  450. * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
  451. * Dual licensed under the MIT and GPL licenses:
  452. * http://www.opensource.org/licenses/mit-license.php
  453. * http://www.gnu.org/licenses/gpl.html
  454. *
  455. */
  456. jQuery.cookie = function(name, value, options) {
  457. if (typeof value != 'undefined') { // name and value given, set cookie
  458. options = options || {};
  459. if (value === null) {
  460. value = '';
  461. options.expires = -1;
  462. }
  463. var expires = '';
  464. if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
  465. var date;
  466. if (typeof options.expires == 'number') {
  467. date = new Date();
  468. date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
  469. } else {
  470. date = options.expires;
  471. }
  472. expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
  473. }
  474. // CAUTION: Needed to parenthesize options.path and options.domain
  475. // in the following expressions, otherwise they evaluate to undefined
  476. // in the packed version for some reason...
  477. var path = options.path ? '; path=' + (options.path) : '';
  478. var domain = options.domain ? '; domain=' + (options.domain) : '';
  479. var secure = options.secure ? '; secure' : '';
  480. document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
  481. } else { // only name given, get cookie
  482. var cookieValue = null;
  483. if (document.cookie && document.cookie != '') {
  484. var cookies = document.cookie.split(';');
  485. for (var i = 0; i < cookies.length; i++) {
  486. var cookie = jQuery.trim(cookies[i]);
  487. // Does this cookie string begin with the name we want?
  488. if (cookie.substring(0, name.length + 1) == (name + '=')) {
  489. cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  490. break;
  491. }
  492. }
  493. }
  494. return cookieValue;
  495. }
  496. };