The version of vichan running on lainchan.org
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

203 lignes
6.9KB

  1. // Thanks to Khorne on #8chan at irc.rizon.net
  2. // https://gitlab.com/aymous/8chan-watchlist
  3. 'use strict';
  4. /* jshint globalstrict:true, quotmark:single */
  5. /* jshint browser:true, jquery:true, devel:true, unused:true, undef:true */
  6. /* global active_page:false, board_name:false */
  7. if(!localStorage.watchlist){
  8. //If the watchlist is undefined in the localStorage,
  9. //initialize it as an empty array.
  10. localStorage.watchlist = '[]';
  11. }
  12. var watchlist = {};
  13. /**
  14. * [render /> Creates a watchlist container and populates it with info
  15. * about each thread that's currently being watched. If the watchlist container
  16. * already exists, it empties it out and repopulates it.]
  17. * @param {[Bool]} reset [If true and the watchlist is rendered, remove it]
  18. */
  19. watchlist.render = function(reset) {
  20. /* jshint eqnull:true */
  21. if (reset == null) reset = false;
  22. /* jshint eqnull:false */
  23. if (reset && $('#watchlist').length) $('#watchlist').remove();
  24. var threads = [];
  25. //Read the watchlist and create a new container for each thread.
  26. JSON.parse(localStorage.watchlist).forEach(function(e, i) {
  27. //look at line 69, that's what (e) is here.
  28. threads.push('<div class="watchlist-inner" id="watchlist-'+i+'">' +
  29. '<span>/'+e[0]+'/ - ' +
  30. '<a href="'+e[3]+'">'+e[1].replace("thread_", _("Thread #"))+'</a>' +
  31. ' ('+e[2]+') </span>' +
  32. '<a class="watchlist-remove">X</a>'+
  33. '</div>');
  34. });
  35. if ($('#watchlist').length) {
  36. //If the watchlist is already there, empty it and append the threads.
  37. $('#watchlist').children('.watchlist-inner').remove();
  38. $('#watchlist').append(threads.join(''));
  39. } else {
  40. //If the watchlist has not yet been rendered, create it.
  41. var menuStyle = getComputedStyle($('.boardlist')[0]);
  42. $((active_page == 'ukko') ? 'hr:first' : (active_page == 'catalog') ? 'body>span:first' : 'form[name="post"]').before(
  43. $('<div id="watchlist">'+
  44. '<div class="watchlist-controls">'+
  45. '<span><a id="clearList">['+_('Clear List')+']</a></span>&nbsp'+
  46. '<span><a id="clearGhosts">['+_('Clear Ghosts')+']</a></span>'+
  47. '</div>'+
  48. threads.join('')+
  49. '</div>').css("background-color", menuStyle.backgroundColor).css("border", menuStyle.borderBottomWidth+" "+menuStyle.borderBottomStyle+" "+menuStyle.borderBottomColor));
  50. }
  51. return this;
  52. };
  53. /**
  54. * [add /> adds the given item to the watchlist]
  55. * @param {[Obj/Str]} sel [An unwrapped jquery selector.]
  56. */
  57. watchlist.add = function(sel) {
  58. var threadName, threadInfo;
  59. var board_name = $(sel).parents('.thread').data('board');
  60. if (active_page === 'thread') {
  61. if ($('.subject').length){
  62. //If a subject is given, use the first 20 characters as the thread name.
  63. threadName = $('.subject').text().substring(0,20);
  64. } else { //Otherwise use the thread id.
  65. threadName = $('.op').parent().attr('id');
  66. }
  67. //board name, thread name as defined above, current amount of posts, thread url
  68. threadInfo = [board_name, threadName, $('.post').length, location.href];
  69. } else if (active_page === 'index' || active_page === 'ukko') {
  70. var postCount;
  71. //Figure out the post count.
  72. if ($(sel).parents('.op').children('.omitted').length) {
  73. postCount = $(sel).parents('.op').children('.omitted').text().split(' ')[0];
  74. } else {
  75. postCount = $(sel).parents('.op').siblings('.post').length+1;
  76. }
  77. //Grab the reply link.;
  78. var threadLink = $(sel).siblings('a:not(.watchThread)').last().attr('href');
  79. //Figure out the thread name. If anon, use the thread id.
  80. if ($(sel).parent().find('.subject').length) {
  81. threadName = $(sel).parent().find('.subject').text().substring(0,20);
  82. } else {
  83. threadName = $(sel).parents('div').last().attr('id');
  84. }
  85. threadInfo = [board_name, threadName, postCount, threadLink];
  86. } else {
  87. alert('Functionality not yet implemented for this type of page.');
  88. return this;
  89. }
  90. //if the thread is already being watched, cancel the function.
  91. if (localStorage.watchlist.indexOf(JSON.stringify(threadInfo)) !== -1) {
  92. return this;
  93. }
  94. var _watchlist = JSON.parse(localStorage.watchlist); //Read the watchlist
  95. _watchlist.push(threadInfo); //Add the new watch item.
  96. localStorage.watchlist = JSON.stringify(_watchlist); //Save the watchlist.
  97. return this;
  98. };
  99. /**
  100. * [remove /> removes the given item from the watchlist]
  101. * @param {[Int]} n [The index at which to remove.]
  102. */
  103. watchlist.remove = function(n) {
  104. var _watchlist = JSON.parse(localStorage.watchlist);
  105. _watchlist.splice(n, 1);
  106. localStorage.watchlist = JSON.stringify(_watchlist);
  107. return this;
  108. };
  109. /**
  110. * [clear /> resets the watchlist to the initial empty array]
  111. */
  112. watchlist.clear = function() {
  113. localStorage.watchlist = '[]';
  114. return this;
  115. };
  116. /**
  117. * [exists /> pings every watched thread to check if it exists and removes it if not]
  118. * @param {[Obj/Str]} sel [an unwrapped jq selector]
  119. */
  120. watchlist.exists = function(sel) {
  121. $.ajax($(sel).children().children('a').attr('href'), {
  122. type :'HEAD',
  123. error: function() {
  124. watchlist.remove(parseInt($(sel).attr('id').split('-')[1])).render();
  125. },
  126. success : function(){
  127. return;
  128. }
  129. });
  130. };
  131. $(document).ready(function(){
  132. if (!(active_page == 'thread' || active_page == 'index' || active_page == 'catalog' || active_page == 'ukko')) {
  133. return;
  134. }
  135. //Append the watchlist toggle button.
  136. $('.boardlist').append('<span>[ <a class="watchlist-toggle" href="#">'+_('watchlist')+'</a> ]</span>');
  137. $('.compact-boardlist').append('<span>[ <a class="watchlist-toggle" href="#">'+_('watchlist')+'</a> ]</span>');
  138. //Append a watch thread button after every OP.
  139. $('.op>.intro').append('<a class="watchThread" href="#">['+_('Watch Thread')+']</a>');
  140. //Draw the watchlist, hidden.
  141. watchlist.render();
  142. //Show or hide the watchlist.
  143. $('.watchlist-toggle').on('click', function(e) {
  144. e.preventDefault();
  145. //if ctrl+click, reset the watchlist.
  146. if (e.ctrlKey) {
  147. watchlist.render(true);
  148. }
  149. if ($('#watchlist').css('display') !== 'none') {
  150. $('#watchlist').css('display', 'none');
  151. } else {
  152. $('#watchlist').css('display', 'block');
  153. } //Shit got really weird with hide/show. Went with css manip. Probably faster anyway.
  154. });
  155. //Trigger the watchlist add function.
  156. //The selector is passed as an argument in case the page is not a thread.
  157. $('.watchThread').on('click', function(e) {
  158. e.preventDefault();
  159. watchlist.add(this).render();
  160. });
  161. //The index is saved in .watchlist-inner so that it can be passed as the argument here.
  162. //$('.watchlist-remove').on('click') won't work in case of re-renders and
  163. //the page will need refreshing. This works around that.
  164. $(document).on('click', '.watchlist-remove', function() {
  165. var item = parseInt($(this).parent().attr('id').split('-')[1]);
  166. watchlist.remove(item).render();
  167. });
  168. //Empty the watchlist and redraw it.
  169. $('#clearList').on('click', function(){
  170. watchlist.clear().render();
  171. });
  172. //Get rid of every watched item that no longer directs to an existing page.
  173. $('#clearGhosts').on('click', function() {
  174. $('.watchlist-inner').each(function(){
  175. watchlist.exists(this);
  176. });
  177. });
  178. });