- // ==UserScript==
- // @name AO3: Tracking
- // @description Track any filterable listing.
- // @namespace https://greasyfork.org/en/scripts/8382-ao3-tracking
- // @author Min
- // @version 1.3.1
- // @grant none
- // @include http://archiveofourown.org/*
- // @include https://archiveofourown.org/*
- // ==/UserScript==
-
-
- (function($) {
-
- if (typeof(Storage) !== 'undefined') {
-
- var tracked_list = '';
- var tracked_array = [];
-
- loadList();
-
- addCss();
- addTrackedMenu();
-
- var main = $('#main');
-
- // if it's a listing of works or bookmarks
- if (main.hasClass('works-index') || main.hasClass('bookmarks-index')) {
-
- var is_tracked = false;
- var is_first_page = true;
-
- // get page url
- var location_url = location.href;
-
- // check if page is already tracked
- var array_index = tracked_array.indexOf(location_url);
- if (array_index > -1) {
- is_tracked = true;
-
- checkOpen();
- }
-
- // make sure it's the first page of the listing
- var current_page = main.find('ol.pagination:first span.current');
- if (current_page.length && current_page.text() !== '1') {
- is_first_page = false;
- }
-
- if (is_first_page) { addTrackButton(); }
- }
-
- // add "Mark all as vieved" button when all listing get checked
- $(document).ajaxStop(function() {
- if ($('#tracked-box').length && !$('#button-check').length) {
- $('#button-mark').css('visibility', 'visible');
- }
- });
- }
-
- // load the saved list
- function loadList() {
-
- tracked_list = localStorage.getItem('ao3tracking_list');
- if (!tracked_list) { tracked_list = ''; }
-
- // make an array of the list
- if (tracked_list.length) {
- tracked_array = tracked_list.split(',,,');
- }
- }
-
- // add current page to tracked listings
- function addToTracked() {
-
- var added = false;
-
- loadList();
-
- // if there's less than 25 tracked
- if (tracked_array.length < 75) {
-
- // ask for name
- var heading = main.find('h2.heading:first');
- var heading_link = heading.find('a');
-
- if (heading_link.length) {
- var suggest = heading_link.text();
- }
- else {
- var suggest = heading.text().replace(/\n/g, '').replace(/^\s+/, '').replace(/(.+of )?\d+ /, '');
- }
-
- var listing_name = prompt('Name for the tracked listing:', suggest);
-
- if (listing_name !== '' && listing_name !== null) {
-
- // remove characters we don't want in the names
- listing_name = listing_name.replace(/,,,/g, ' ');
-
- var listing_count = heading.text().replace(/\n/g, '').replace(/^\s+/, '').replace(/.*\d+ - \d+ of /, '').replace(/(\d+)(.+)/, '$1');
-
- // add name, url, count
- tracked_array.push(listing_name, location_url, listing_count);
- tracked_list = tracked_array.join(',,,');
-
- // save the updated list
- localStorage.setItem('ao3tracking_list', tracked_list);
-
- added = true;
- }
- }
- else {
- alert("You're already tracking 25 listings. Remove some first.");
- }
-
- return added;
- }
-
- // remove a given url from tracked listings
- function removeFromTracked(url) {
-
- var removed = false;
-
- loadList();
-
- var index = tracked_array.indexOf(url);
-
- // if the url is on the saved list
- if (index > -1) {
-
- // ask for confirmation
- var confirmed = confirm('Sure you want to remove "' + tracked_array[index-1] + '"?');
-
- if (confirmed) {
- // remove name, url, count
- tracked_array.splice(index-1, 3);
- tracked_list = tracked_array.join(',,,');
-
- // save the updated list
- localStorage.setItem('ao3tracking_list', tracked_list);
-
- removed = true;
- }
- }
-
- return removed;
- }
-
- // check open page for new works
- function checkOpen() {
-
- var heading = main.find('h2.heading:first');
-
- // get a count of new works
- var current_count = parseInt(heading.text().replace(/\n/g, '').replace(/^\s+/, '').replace(/.*\d+ - \d+ of /, '').replace(/(\d+)(.+)/, '$1'));
- var saved_count = parseInt(tracked_array[array_index+1]);
- var new_count = current_count - saved_count;
-
- if (new_count !== 0) {
-
- heading.append(' <span id="new-works">(' + new_count + ' new)</span> <a id="mark-viewed">[mark viewed]</a>');
-
- $('#mark-viewed').click(function() {
-
- loadList();
-
- var array_index = tracked_array.indexOf(location_url);
- if (array_index > -1) {
- // update the count
- tracked_array[array_index+1] = current_count;
- tracked_list = tracked_array.join(',,,');
-
- // save the updated list
- localStorage.setItem('ao3tracking_list', tracked_list);
- }
-
- $('#new-works').detach();
- $(this).detach();
- });
- }
- }
-
- // check the tracked listings for new works
- function checkForNew() {
-
- // check if it's more than 8 hours since last check
- var last_check = localStorage.getItem('ao3tracking_lastcheck');
- if (!last_check) { var last_check = 0; }
- else { last_check = parseInt(last_check); }
-
- var now = new Date();
- now = now.getTime();
- var wait = 28800000 - (now - last_check);
-
- if (wait < 0) {
-
- localStorage.setItem('ao3tracking_lastcheck', now);
-
- // for each tracked listing
- $('#tracked-box li.tracked-listing').each(function() {
-
- var tracked_url = $(this).find('a').attr('href');
- var listing_id = $(this).attr('id');
-
- tracked_url += ' #main h2.heading:first';
-
- // load heading of the tracked page
- $(this).find('span.tracked-current').load(tracked_url, function() {
-
- var listing = $('#' + listing_id);
-
- // get a count of new works
- var current_count = parseInt(listing.find('span.tracked-current').text().replace(/\n/g, '').replace(/^\s+/, '').replace(/.*\d+ - \d+ of /, '').replace(/(\d+)(.+)/, '$1'));
- listing.find('span.tracked-current').html(current_count);
- var saved_count = parseInt(listing.find('span.tracked-saved').text());
- var new_count = current_count - saved_count;
-
- listing.find('span.tracked-new').text('(' + new_count + ' new)');
-
- if (new_count !== 0) {
- listing.find('span.tracked-new').addClass('new-stuff');
- listing.parent().prepend(listing);
- }
- else {
- listing.find('span.tracked-new').addClass('no-new-stuff');
- }
- });
- });
- }
- else {
- var hours = Math.floor(wait/3600000);
- var minutes = Math.ceil((wait%3600000)/60000);
-
- var warning = $('<p style="color: #990000;"></p>');
-
- if (hours > 0) {
- warning.html('<strong>Please be kind to the AO3 servers!</strong> Wait ' + hours + ' hour(s) and ' + minutes + ' minute(s) more before another check.');
- }
- else {
- warning.html('<strong>Please be kind to the AO3 servers!</strong> Wait ' + minutes + ' more minute(s) before another check.');
- }
-
- $('#tracked-box p.actions').after(warning);
- }
- }
-
- // add the 'Track This' button
- function addTrackButton() {
-
- var work_filters = $('form.filters dd.submit.actions:first');
-
- var track_this_button = $('<input type="button" value="Track This" class="track-this"></input>');
- track_this_button.click(function() {
- var added = addToTracked();
- if (added) {
- track_this_button.detach();
- work_filters.prepend(untrack_this_button);
- }
- });
-
- var untrack_this_button = $('<input type="button" value="Untrack This" class="track-this"></input>');
- untrack_this_button.click(function() {
- var removed = removeFromTracked(location_url);
- if (removed) {
- untrack_this_button.detach();
- work_filters.prepend(track_this_button);
- }
- });
-
- // if the page is already tracked
- if (is_tracked) {
- work_filters.prepend(untrack_this_button);
- }
- // if it's not tracked
- else {
- work_filters.prepend(track_this_button);
- }
- }
-
- // rearrange things on the list
- function editList() {
-
- var box_list = $('#box-list');
-
- box_list.find('li.tracked-listing').each(function() {
- $(this).prepend('<span class="up-arrow">↑</span> <span class="down-arrow">↓</span> <span class="cross">✗</span> ');
- });
-
- box_list.on('click', 'span.up-arrow', function() {
- $(this).parent().prev().before($(this).parent());
- });
-
- box_list.on('click', 'span.down-arrow', function() {
- $(this).parent().next().after($(this).parent());
- });
-
- box_list.on('click', 'span.cross', function() {
- $(this).parent().detach();
- });
- }
-
- // save list after edits
- function saveList() {
-
- tracked_array = [];
-
- // get name, url, count for all listings
- $('#tracked-box li.tracked-listing').each(function() {
-
- var name = $(this).find('a').text();
- var url = $(this).find('a').attr('href');
- var count = $(this).find('span.tracked-saved').text();
-
- tracked_array.push(name, url, count);
- });
-
- // update and save the new list
- tracked_list = tracked_array.join(',,,');
- localStorage.setItem('ao3tracking_list', tracked_list);
-
- // reload the box
- $('#tracked-box').detach();
- $('#tracked-bg').detach();
- showBox();
- }
-
- // update the listings counts
- function markAllViewed() {
-
- loadList();
-
- // get the current count for all listings
- $('#tracked-box li.tracked-listing').each(function() {
-
- var url = $(this).find('a').attr('href');
- var current_count = $(this).find('span.tracked-current').text();
-
- var index = tracked_array.indexOf(url);
- if (index > -1) {
- tracked_array[index+1] = current_count;
- }
- });
-
- // update and save the new list
- tracked_list = tracked_array.join(',,,');
- localStorage.setItem('ao3tracking_list', tracked_list);
-
- // reload the box
- $('#tracked-box').detach();
- $('#tracked-bg').detach();
- showBox();
- }
-
- // show the box with tracked listings
- function showBox() {
-
- var tracked_bg = $('<div id="tracked-bg"></div>');
-
- var tracked_box = $('<div id="tracked-box"></div>');
-
- var box_buttons = $('<p class="actions"></p>');
-
- var box_button_check = $('<input type="button" id="button-check" value="Check for new"></input>');
- box_button_check.click(function() {
- box_button_edit.after(box_button_mark);
- checkForNew();
- box_button_edit.detach();
- box_button_check.detach();
- });
-
- var box_button_edit = $('<input type="button" id="button-edit" value="Edit list"></input>');
- box_button_edit.click(function() {
- editList();
- box_button_edit.after(box_button_save, box_button_cancel);
- box_button_check.detach();
- box_button_edit.detach();
- });
-
- var box_button_save = $('<input type="button" id="button-save" value="Save list"></input>');
- box_button_save.click(function() { saveList(); });
-
- var box_button_cancel = $('<input type="button" id="button-cancel" value="Cancel edits"></input>');
- box_button_cancel.click(function() {
- tracked_box.detach();
- tracked_bg.detach();
- showBox();
- });
-
- var box_button_mark = $('<input type="button" id="button-mark" style="visibility: hidden;" value="Mark all as viewed"></input>');
- box_button_mark.click(function() { markAllViewed(); });
-
- var box_button_close = $('<input type="button" id="button-close" value="Close"></input>');
- box_button_close.click(function() {
- tracked_box.detach();
- tracked_bg.detach();
- });
-
- var box_header = $('<h3></h3>').text('Tracked listings [' + tracked_array.length/3 + '/25]:');
- var box_list = $('<ul id="box-list"></ul>');
-
- tracked_box.append(box_buttons, box_header, box_list);
-
- // if there are saved listings
- if (tracked_array.length > 2) {
- for (var i = 0; i < tracked_array.length; i += 3) {
-
- var listing = $('<li id="tracked-listing-' + i/3 + '" class="tracked-listing"></li>').html('<a href="' + tracked_array[i+1] + '">' + tracked_array[i] + '</a> <span class="tracked-new"></span> <span class="tracked-saved">' + tracked_array[i+2] + '</span> <span class="tracked-current"></span>');
- box_list.append(listing);
- }
- }
- else {
- var no_listings = $('<li style="opacity: 0.5; font-style: oblique;"></li>').html("you're not tracking anything yet!");
- box_list.append(no_listings);
-
- box_button_check.css('visibility', 'hidden');
- box_button_edit.css('visibility', 'hidden');
- }
-
- box_buttons.append(box_button_check, box_button_edit, box_button_close);
-
- $('body').append(tracked_bg, tracked_box);
- }
-
- // attach the menu
- function addTrackedMenu() {
-
- // get the header menu
- var header_menu = $('ul.primary.navigation.actions');
-
- // create and insert menu button
- var tracked_button = $('<input class="button" type="button" value="Tracked"></input>');
- header_menu.find('#search').prepend(tracked_button);
- tracked_button.click(function() {
- if ($('#tracked-box').length == 0) {
- loadList();
- showBox();
- }
- });
- }
-
- // add css rules to page head
- function addCss() {
- var style = $('<style type="text/css"></style>').appendTo($('head'));
-
- var css = '#tracked-box {position: fixed; top: 0px; bottom: 0px; left: 0px; right: 0px; width: 60%; height: 80%; max-width: 800px; margin: auto; overflow-y: auto; border: 10px solid #eee; box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.2); padding: 0 20px; background-color: #ffffff; z-index: 999;}\
- #tracked-bg {position: fixed; width: 100%; height: 100%; background-color: #000000; opacity: 0.7; z-index: 998;}\
- input[type="button"] {height: auto;}\
- input.track-this {margin-bottom: 10px;}\
- #tracked-box p.actions {float: none; text-align: left;}\
- #button-save {font-weight: bold;}\
- #button-close {float: right;}\
- #tracked-box li span.tracked-new.new-stuff {font-weight: bold;}\
- #tracked-box li span.tracked-new.no-new-stuff {opacity: 0.5;}\
- #tracked-box li span.tracked-current, #tracked-box li span.tracked-saved {display: none;}\
- #new-works {font-weight: bold;}';
-
- style.append(css);
- }
- })(jQuery);