// Thanks to Khorne on #8chan at irc.rizon.net // https://gitlab.com/aymous/8chan-watchlist 'use strict'; /* jshint globalstrict:true, quotmark:single */ /* jshint browser:true, jquery:true, devel:true, unused:true, undef:true */ /* global active_page:false, board_name:false */ if(!localStorage.watchlist){ //If the watchlist is undefined in the localStorage, //initialize it as an empty array. localStorage.watchlist = '[]'; } var watchlist = {}; /** * [render /> Creates a watchlist container and populates it with info * about each thread that's currently being watched. If the watchlist container * already exists, it empties it out and repopulates it.] * @param {[Bool]} reset [If true and the watchlist is rendered, remove it] */ watchlist.render = function(reset) { /* jshint eqnull:true */ if (reset == null) reset = false; /* jshint eqnull:false */ if (reset && $('#watchlist').length) $('#watchlist').remove(); var threads = []; //Read the watchlist and create a new container for each thread. JSON.parse(localStorage.watchlist).forEach(function(e, i) { //look at line 69, that's what (e) is here. threads.push('
' + 'Board: '+e[0]+' ' + 'Thread: '+''+e[1]+' ' + 'Replies: '+e[2]+' ' + '[Unwatch]'+ '
'); }); if ($('#watchlist').length) { //If the watchlist is already there, empty it and append the threads. $('#watchlist').children('.watchlist-inner').remove(); $('#watchlist').append(threads.join('')); } else { //If the watchlist has not yet been rendered, create it. $('form[name="post"]').before( $('
'+ '
'+ '[Clear List] '+ '[Clear Ghosts]'+ '
'+ threads.join('')+ '
').css({ background: $('.reply').css('background'), borderColor : $('.reply').css('border-color') })); } return this; }; /** * [add /> adds the given item to the watchlist] * @param {[Obj/Str]} sel [An unwrapped jquery selector.] */ watchlist.add = function(sel) { var threadName, threadInfo; if (active_page === 'thread') { if ($('.subject').length){ //If a subject is given, use the first 20 characters as the thread name. threadName = $('.subject').text().substring(0,20); } else { //Otherwise use the thread id. threadName = $('.op').parent().attr('id'); } //board name, thread name as defined above, current amount of posts, thread url threadInfo = [board_name, threadName, $('.post').length, location.href]; } else if (active_page === 'index') { var postCount; //Figure out the post count. if ($(sel).parents('.op').children('.omitted').length) { postCount = $(sel).parents('.op').children('.omitted').text().split(' ')[0]; } else { postCount = $(sel).parents('.op').siblings('.post').length+1; } //Grab the reply link. var threadLink = $(sel).siblings('a:contains("[Reply]")').attr('href'); //Figure out the thread name. If anon, use the thread id. if ($(sel).parent().find('.subject').length) { threadName = $(sel).parent().find('.subject').text().substring(0,20); } else { threadName = $(sel).parents('div').last().attr('id'); } threadInfo = [board_name, threadName, postCount, threadLink]; } else { alert('Functionality not yet implemented for this type of page.'); return this; } //if the thread is already being watched, cancel the function. if (localStorage.watchlist.indexOf(JSON.stringify(threadInfo)) !== -1) { return this; } var _watchlist = JSON.parse(localStorage.watchlist); //Read the watchlist _watchlist.push(threadInfo); //Add the new watch item. localStorage.watchlist = JSON.stringify(_watchlist); //Save the watchlist. return this; }; /** * [remove /> removes the given item from the watchlist] * @param {[Int]} n [The index at which to remove.] */ watchlist.remove = function(n) { var _watchlist = JSON.parse(localStorage.watchlist); _watchlist.splice(n, 1); localStorage.watchlist = JSON.stringify(_watchlist); return this; }; /** * [clear /> resets the watchlist to the initial empty array] */ watchlist.clear = function() { localStorage.watchlist = '[]'; return this; }; /** * [exists /> pings every watched thread to check if it exists and removes it if not] * @param {[Obj/Str]} sel [an unwrapped jq selector] */ watchlist.exists = function(sel) { $.ajax($(sel).children().children('a').attr('href'), { type :'HEAD', error: function() { watchlist.remove(parseInt($(sel).attr('id').split('-')[1])).render(); }, success : function(){ return; } }); }; $(document).ready(function(){ //Append the watchlist toggle button. $('.boardlist').append('[ watchlist ]'); //Append a watch thread button after every OP. $('.op>.intro').append('[Watch Thread]'); //Draw the watchlist, hidden. watchlist.render(); //Show or hide the watchlist. $('#watchlist-toggle').on('click', function(e) { //if ctrl+click, reset the watchlist. if (e.ctrlKey) { watchlist.render(true); } if ($('#watchlist').css('display') !== 'none') { $('#watchlist').css('display', 'none'); } else { $('#watchlist').css('display', 'block'); } //Shit got really weird with hide/show. Went with css manip. Probably faster anyway. }); //Trigger the watchlist add function. //The selector is passed as an argument in case the page is not a thread. $('.watchThread').on('click', function() { watchlist.add(this).render(); }); //The index is saved in .watchlist-inner so that it can be passed as the argument here. //$('.watchlist-remove').on('click') won't work in case of re-renders and //the page will need refreshing. This works around that. $(document).on('click', '.watchlist-remove', function() { var item = parseInt($(this).parent().attr('id').split('-')[1]); watchlist.remove(item).render(); }); //Empty the watchlist and redraw it. $('#clearList').on('click', function(){ watchlist.clear().render(); }); //Get rid of every watched item that no longer directs to an existing page. $('#clearGhosts').on('click', function() { $('.watchlist-inner').each(function(){ watchlist.exists(this); }); }); });