PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/app/assets/javascripts/auto/cf_threads.js

http://github.com/ckruse/cforum
JavaScript | 399 lines | 325 code | 70 blank | 4 comment | 77 complexity | 6863fa14ad704791b9d13a67640b3e2c MD5 | raw file
Possible License(s): AGPL-3.0
  1. /* -*- coding: utf-8 -*- */
  2. /* global cforum, Mustache, t, setDismissHandlers, autohideAlerts, hasLocalstorage, uconf */
  3. cforum.cf_threads = {
  4. numThreads: 0,
  5. numMessages: 0,
  6. newMessages: [],
  7. removeNewMessage: function(mids) {
  8. var difference = [];
  9. $.grep(cforum.cf_threads.newMessages, function(el) {
  10. if($.inArray(el, mids) == -1) {
  11. difference.push(el);
  12. }
  13. });
  14. cforum.cf_threads.newMessages = difference;
  15. },
  16. new: function() {
  17. cforum.cf_threads.initGlobal();
  18. cforum.tags.initTags();
  19. cforum.cf_threads.initCursor();
  20. cforum.messages.initMarkdown("message_input");
  21. cforum.messages.initPreview("message_input", "cf_thread_message_problematic_site");
  22. cforum.messages.initMaxLengthWarnings();
  23. cforum.replacements("#message_input", true);
  24. cforum.messages.initEmojis("#message_input", ".btn-group.groupUtil");
  25. },
  26. create: function() {
  27. cforum.cf_threads.initGlobal();
  28. cforum.tags.initTags();
  29. cforum.messages.initMarkdown("message_input");
  30. cforum.messages.initPreview("message_input", "cf_thread_message_problematic_site");
  31. cforum.messages.initMaxLengthWarnings();
  32. cforum.replacements("#message_input", true);
  33. },
  34. index: function() {
  35. cforum.events.on('thread:create', cforum.cf_threads.newThreadArriving);
  36. cforum.events.on('message:create', cforum.cf_threads.newMessageArriving);
  37. cforum.events.on('thread:read', cforum.cf_threads.updateThread);
  38. cforum.events.on('message:read', cforum.cf_threads.updateThread);
  39. if(!cforum.currentUser) {
  40. cforum.cf_threads.initOpenClose();
  41. }
  42. },
  43. showNewAlert: function() {
  44. var alert = $("#new_messages_arrived");
  45. var append = false;
  46. if(!alert.length) {
  47. alert = $("<div class=\"cf-success cf-alert\" id=\"new_messages_arrived\"><button type=\"button\" class=\"close\" data-dismiss=\"cf-alert\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button></div>");
  48. append = true;
  49. }
  50. alert.text(Mustache.render(
  51. t('messages_threads'),
  52. {threads: cforum.cf_threads.numThreads,
  53. messages: cforum.cf_threads.numMessages}));
  54. if(append) {
  55. $("#alerts-container").append(alert);
  56. setDismissHandlers();
  57. autohideAlerts();
  58. }
  59. },
  60. showNewThread: function(message) {
  61. var sortMethod = uconf('sort_threads');
  62. if(sortMethod != 'ascending' && sortMethod != 'descending' && sortMethod != 'newest-first') {
  63. sortMethod = 'descending';
  64. }
  65. var url = cforum.baseUrl +
  66. (cforum.currentForum ? cforum.currentForum.slug : 'all') +
  67. message.thread.slug;
  68. $.get(url).
  69. done(function(data) {
  70. switch(sortMethod) {
  71. case 'newest-first':
  72. case 'descending':
  73. if(document.location.href.indexOf('p=0') != -1 || document.location.href.indexOf('p=') == -1) {
  74. var sticky = $("[data-js=threadlist] .sticky:last");
  75. if(sticky.length === 0) {
  76. $("[data-js=threadlist]").prepend(data);
  77. }
  78. else {
  79. sticky.after(data);
  80. }
  81. }
  82. break;
  83. case 'ascending':
  84. if($(".cf-pages .last").hasClass('disabled')) {
  85. $("[data-js=threadlist]").append(data);
  86. }
  87. break;
  88. }
  89. cforum.cf_threads.newMessages.push(message.message.message_id);
  90. var m;
  91. for(var i = 0; i < cforum.cf_threads.newMessages.length; ++i) {
  92. m = $("#m" + cforum.cf_threads.newMessages[i]);
  93. if(!m.hasClass('new')) {
  94. m.addClass('new');
  95. }
  96. }
  97. });
  98. },
  99. newThreadArriving: function(event, message) {
  100. cforum.cf_threads.numThreads += 1;
  101. cforum.cf_threads.numMessages += 1;
  102. if(cforum.currentUser && message.message.user_id == cforum.currentUser.user_id) {
  103. return;
  104. }
  105. if(uconf('load_messages_via_js') != 'no') {
  106. window.setTimeout(function() {
  107. cforum.cf_threads.showNewThread(message);
  108. cforum.events.trigger("update", message);
  109. cforum.events.trigger("update:thread", message);
  110. }, 500);
  111. }
  112. cforum.cf_threads.showNewAlert();
  113. cforum.updateFavicon();
  114. },
  115. updateThread: function(event, message) {
  116. var thread = $("#t" + message.thread.thread_id);
  117. if(message.message) {
  118. cforum.cf_threads.removeNewMessage([message.message.message_id]);
  119. }
  120. else {
  121. cforum.cf_threads.removeNewMessage($.map(message.thread.messages, function(el) {
  122. return el.message_id;
  123. }));
  124. }
  125. if(thread.length == 0) {
  126. return;
  127. }
  128. var url = cforum.baseUrl +
  129. (cforum.currentForum ? cforum.currentForum.slug : 'all') +
  130. message.thread.slug;
  131. window.setTimeout(function() {
  132. $.get(url, function(data) {
  133. thread.replaceWith(data);
  134. cforum.updateTitle();
  135. cforum.events.trigger("update", message);
  136. cforum.events.trigger("update:thread", message);
  137. });
  138. }, 500);
  139. },
  140. newMessageArriving: function(event, message) {
  141. cforum.cf_threads.numMessages += 1;
  142. if(cforum.currentUser && message.message.user_id == cforum.currentUser.user_id) {
  143. return;
  144. }
  145. cforum.cf_threads.showNewAlert();
  146. if(uconf('load_messages_via_js') != 'no') {
  147. var url = cforum.baseUrl +
  148. (cforum.currentForum ? cforum.currentForum.slug : 'all') +
  149. message.thread.slug;
  150. $.get(url).
  151. done(function(data) {
  152. $("#t" + message.thread.thread_id).replaceWith(data);
  153. if(uconf('sort_threads') == 'newest-first') {
  154. var sticky = $("[data-js=threadlist] .sticky:last");
  155. if(sticky.length === 0) {
  156. $("[data-js=threadlist]").prepend($("#t" + message.thread.thread_id));
  157. }
  158. else {
  159. sticky.after($("#t" + message.thread.thread_id));
  160. }
  161. }
  162. cforum.cf_threads.newMessages.push(message.message.message_id);
  163. var m;
  164. for(var i = 0; i < cforum.cf_threads.newMessages.length; ++i) {
  165. m = $("#m" + cforum.cf_threads.newMessages[i]);
  166. if(!m.hasClass('new')) {
  167. m.addClass('new');
  168. }
  169. }
  170. cforum.events.trigger("update", message);
  171. cforum.events.trigger("update:message", message);
  172. });
  173. }
  174. cforum.updateFavicon();
  175. },
  176. initGlobal: function() {
  177. if(!cforum.currentForum) {
  178. $("#cf_thread_forum_id").on('change', function() {
  179. var val = $(this).val();
  180. for(var i = 0; i < cforum.userForums.length; ++i) {
  181. if(cforum.userForums[i].forum_id == val) {
  182. cforum.currentForum = cforum.userForums[i];
  183. break;
  184. }
  185. }
  186. });
  187. $("#cf_thread_forum_id").trigger('change');
  188. }
  189. },
  190. initCursor: function() {
  191. var content = $("#message_input");
  192. var subj = $("#cf_thread_message_subject");
  193. var author = $("#cf_thread_message_author");
  194. cforum.cf_threads.setCursor(author, subj, content);
  195. },
  196. setCursor: function(author, subject, content) {
  197. if(!subject.val()) {
  198. setTimeout(function() { subject.focus(); }, 0);
  199. }
  200. else {
  201. if(cforum.currentUser) {
  202. setTimeout(function() { content.focus(); }, 0);
  203. cforum.cf_threads.setCursorInContent(content);
  204. }
  205. else {
  206. if(!author.val()) {
  207. setTimeout(function() { author.focus(); }, 0);
  208. }
  209. else {
  210. setTimeout(function() { content.focus(); }, 0);
  211. cforum.cf_threads.setCursorInContent(content);
  212. }
  213. }
  214. }
  215. },
  216. setCursorInContent: function(content) {
  217. var cnt = content.val();
  218. var i;
  219. for(i = 0; i < cnt.length; ++i) {
  220. if(cnt.substr(i, 1) == '>' &&
  221. (i === 0 || cnt.substr(i - 1, 1) == "\n") &&
  222. cnt.substr(i + 1, 1) == ' ') {
  223. content.setSelection(i, i);
  224. return;
  225. }
  226. }
  227. // we couldn't find a quote, so we set cursor after the first empty line
  228. var newline = 0;
  229. for(i = 0; i < cnt.length; ++i) {
  230. if(cnt.substr(i - 1, 1) == "\012") {
  231. newline++;
  232. }
  233. else if(cnt.substr(i - 1, 1) == "\015") {
  234. continue;
  235. }
  236. else {
  237. newline = 0;
  238. }
  239. if(newline == 2) {
  240. content.setSelection(i, i);
  241. return;
  242. }
  243. }
  244. },
  245. initOpenClose: function() {
  246. $("#link-archiv").after(' <li id="open-close-all-threads" class="close-all"><a href="#">' + t('close_all_threads') + "</a></li>");
  247. $("div[data-js=threadlist] .thread > header").
  248. prepend("<i class=\"icon-thread open\"> </i>");
  249. $("div[data-js=threadlist] .thread > header > i").
  250. click(cforum.cf_threads.toggleThread);
  251. $("#open-close-all-threads").click(cforum.cf_threads.toggleAllThreads);
  252. if(hasLocalstorage()) {
  253. var has_open = false;
  254. $("div[data-js=threadlist] .thread").each(function() {
  255. var $this = $(this);
  256. var id = $this.attr('id');
  257. if(localStorage['closed-' + id]) {
  258. $this.children("ol").css('display', 'none');
  259. $this.find("header > i.icon-thread").
  260. removeClass("open").
  261. addClass('closed');
  262. }
  263. else {
  264. has_open = true;
  265. }
  266. });
  267. if(!has_open) {
  268. $("#open-close-all-threads a").text(t('open_all_threads'));
  269. $("#open-close-all-threads").
  270. removeClass("close-all").
  271. addClass("open-all");
  272. }
  273. }
  274. },
  275. toggleThread: function() {
  276. var $this = $(this);
  277. var elem = $this.closest("article");
  278. if($this.hasClass('open')) {
  279. $this.removeClass("open").addClass('closed');
  280. elem.children("ol").slideUp('fast');
  281. if(hasLocalstorage()) {
  282. localStorage['closed-' + elem.attr('id')] = true;
  283. }
  284. }
  285. else {
  286. $this.removeClass("closed").addClass('open');
  287. elem.children("ol").slideDown('fast');
  288. if(hasLocalstorage()) {
  289. localStorage.removeItem('closed-' + elem.attr('id'));
  290. }
  291. }
  292. },
  293. toggleAllThreads: function(ev) {
  294. ev.preventDefault();
  295. if($(this).hasClass('open-all')) {
  296. $("div[data-js=threadlist] .thread > ol").
  297. css('display', 'block');
  298. $("div[data-js=threadlist] .thread > header > i").
  299. addClass('open').
  300. removeClass("closed");
  301. $("#open-close-all-threads a").text(t('close_all_threads'));
  302. $("#open-close-all-threads").
  303. removeClass("open-all").
  304. addClass("close-all");
  305. if(hasLocalstorage()) {
  306. $("div[data-js=threadlist] .thread").each(function() {
  307. localStorage.removeItem('closed-' + $(this).attr('id'));
  308. });
  309. }
  310. }
  311. else {
  312. $("div[data-js=threadlist] .thread > ol").
  313. css('display', 'none');
  314. $("div[data-js=threadlist] .thread > header > i").
  315. addClass('closed').
  316. removeClass("open");
  317. $("#open-close-all-threads a").text(t('open_all_threads'));
  318. $("#open-close-all-threads").
  319. removeClass("close-all").
  320. addClass("open-all");
  321. if(hasLocalstorage()) {
  322. $("div[data-js=threadlist] .thread").each(function() {
  323. localStorage['closed-' + $(this).attr('id')] = true;
  324. });
  325. }
  326. }
  327. }
  328. };
  329. /* eof */