AO3: Kudosed and seen history

Highlight or hide works you kudosed/marked as seen.

当前为 2015-03-20 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        AO3: Kudosed and seen history
// @description Highlight or hide works you kudosed/marked as seen.
// @namespace	https://greasyfork.org/scripts/5835-ao3-kudosed-and-seen-history
// @author	Min
// @version	1.3
// @history	1.3 - option to collapse blurbs of seen works
// @history	1.2.1 - double click on date marks work as seen
// @history	1.2 - check for bookmarks you left, changes to the menu
// @grant       none
// @include     http://archiveofourown.org/*
// @include     https://archiveofourown.org/*
// ==/UserScript==


(function($) {
	
	if (typeof(Storage) !== 'undefined') {
		
		var username = localStorage.getItem('kudoshistory_username');
		
		// if there's no saved username, look for it on the page or ask
		if (!username) {
			var userlink = $('#greeting').find('[href^="/users/"]');
			
			if (userlink.length) {
				var userlink_parts = userlink.attr('href').split('/');
				var username = userlink_parts[2];
				localStorage.setItem('kudoshistory_username', username);
			}
			else {
				var username = prompt('AO3: Kudosed and seen history\n\nYour AO3 username:');
				localStorage.setItem('kudoshistory_username', username);
			}
		}
		
		// check the 'hide seen works' setting
		var hide_seen = 0;
		var hide_seen_set = localStorage.getItem('kudoshistory_hide');
		switch (hide_seen_set) {
			case 'yes':
				hide_seen = 1;
				break;
			case 'collapse':
				hide_seen = 2;
		}
		
		// check the 'mark as seen on open' setting
		var auto_seen = false;
		var auto_seen_set = localStorage.getItem('kudoshistory_autoseen');
		if (auto_seen_set == 'yes') {
			auto_seen = true;
		}
		
		// uncomment the next three lines if you need to clear your local lists (then comment them again after refreshing the page once)
		// localStorage.removeItem('kudoshistory_kudosed');
		// localStorage.removeItem('kudoshistory_checked');
		// localStorage.removeItem('kudoshistory_seen');

		var list_kudosed = localStorage.getItem('kudoshistory_kudosed');
		var list_checked = localStorage.getItem('kudoshistory_checked');
		var list_seen = localStorage.getItem('kudoshistory_seen');
		
		if (!list_kudosed) { var list_kudosed = ','; }
		if (!list_checked) { var list_checked = ','; }
		if (!list_seen) { var list_seen = ','; }
		
		$(document).ajaxStop(function() {
			localStorage.setItem('kudoshistory_kudosed', list_kudosed);
			localStorage.setItem('kudoshistory_checked', list_checked);
			localStorage.setItem('kudoshistory_seen', list_seen);
		});
		
		// add css rules for kudosed works
		addCss(false);
		
		// if there's a list of works or bookmarks, add menu
		var found_blurbs = $('li.work.blurb').add('li.bookmark.blurb');
		
		if (found_blurbs.length) {
			addSeenMenu();
		}
		
		// for each work blurb
		$('li.work.blurb').not('.deleted').each(function() {
			
			// get work id
			var work_id = $(this).attr('id').replace('work_', '');
			
			blurbCheck(work_id, 'work_' + work_id, $(this));
			
			// double click on date marks work as seen
			var work_date = $(this).not('.marked-seen').not('.has-kudos').find('p.datetime');
			if (work_date.length) {
				work_date.one('dblclick', function() {
					list_seen = localStorage.getItem('kudoshistory_seen');
					list_seen = ',' + work_id + list_seen;
					localStorage.setItem('kudoshistory_seen', list_seen);
					$('#work_' + work_id).addClass('marked-seen');
				});
			}
		});
		
		// for each bookmark blurb
		$('li.bookmark.blurb').not('.deleted').each(function() {
			
			// get bookmark and work ids
			var bookmark_id = $(this).attr('id');
			var work_link = $(this).find('h4 a:first').attr('href');
			
			// if it's not a series bookmark
			if (work_link.indexOf('series') == -1) {
				var work_id = work_link.split('/').pop();
				blurbCheck(work_id, bookmark_id, $(this));
			}
		});
		
		// if it's a work page
		if ($('#workskin').length) {
			
			// get work id
			var url_parts = location.pathname.split('/');
			var work_id = url_parts[url_parts.indexOf('works')+1];
			
			// check if work id is on the seen list
			var is_seen = list_seen.indexOf(',' + work_id + ',');
			
			if (auto_seen) {
				if (is_seen == -1) {
					list_seen = ',' + work_id + list_seen;
					is_seen = 1;
				}
				$('dl.work.meta.group').addClass('marked-seen');
			}
			else if (is_seen > -1) {
				$('dl.work.meta.group').addClass('marked-seen');
			}
			
			addSeenButtons();
			
			// if work id is on the kudosed list
			if (list_kudosed.indexOf(',' + work_id + ',') > -1) {
				$('dl.work.meta.group').addClass('has-kudos');
			}
			else {
				var found_kudos = false;
				
				// check if there are kudos from the user
				var user_kudos = $('#kudos').find('[href="/users/' + username + '"]');
				
				if (user_kudos.length) {
					// highlight blurb and add work id to kudosed list
					list_kudosed = ',' + work_id + list_kudosed;
					list_checked = list_checked.replace(',' + work_id + ',', ',');
					$('dl.work.meta.group').addClass('has-kudos');
					found_kudos = true;
				}
				else if (list_checked.indexOf(',' + work_id + ',') == -1) {
					// add work id to checked list
					list_checked = ',' + work_id + list_checked;
				}
				
				if (!found_kudos) {
					$('#new_kudo').click(function() {
						list_kudosed = localStorage.getItem('kudoshistory_kudosed');
						list_checked = localStorage.getItem('kudoshistory_checked');
						list_kudosed = ',' + work_id + list_kudosed;
						list_checked = list_checked.replace(',' + work_id + ',', ',');
						$('dl.work.meta.group').addClass('has-kudos');
						localStorage.setItem('kudoshistory_kudosed', list_kudosed);
						localStorage.setItem('kudoshistory_checked', list_checked);
					}); 
				}
			}
			
			// check if it's bookmarked
			var bookmark_button_text = $('a.bookmark_form_placement_open:first').text();
			
			if (bookmark_button_text.indexOf('Edit') > -1) {
				// highlight blurb
				$('dl.work.meta.group').addClass('is-bookmarked');
			}
		}
		
		// keep the kudos and checked lists under 200k characters (~25k works)
		if (list_kudosed.length > 200000) {
			list_kudosed = list_kudosed.slice(0,180000);
		}
		if (list_checked.length > 200000) {
			list_checked = list_checked.slice(0,180000);
		}
		
		// keep the seen list under 2mil characters (~250k works)
		if (list_seen.length > 2000000) {
			list_seen = list_seen.slice(0,1900000);
		}
		
		// save all lists
		try {
			localStorage.setItem('kudoshistory_kudosed', list_kudosed);
			localStorage.setItem('kudoshistory_checked', list_checked);
			localStorage.setItem('kudoshistory_seen', list_seen);
		}
		catch(e) {
			list_seen = list_seen.slice(0,list_seen.length*0.9);
			localStorage.setItem('kudoshistory_kudosed', list_kudosed);
			localStorage.setItem('kudoshistory_checked', list_checked);
			localStorage.setItem('kudoshistory_seen', list_seen);
		}
	}
	
	// check if work is on lists
	function blurbCheck(work_id, blurb_id, blurb) {
		
		// if work id is on the kudosed list
		if (list_kudosed.indexOf(',' + work_id + ',') > -1) {
			blurb.addClass('has-kudos');
			list_kudosed = ',' + work_id + list_kudosed.replace(',' + work_id + ',', ',');
		}
		// if work id is on the seen list
		else if (list_seen.indexOf(',' + work_id + ',') > -1) {
			blurb.addClass('marked-seen');
			list_seen = ',' + work_id + list_seen.replace(',' + work_id + ',', ',');
		}
		// if work id is on the checked list
		else if (list_checked.indexOf(',' + work_id + ',') > -1) {
			list_checked = ',' + work_id + list_checked.replace(',' + work_id + ',', ',');
		}
		else {
			// add a div to the blurb that will house the kudos
			blurb.append('<div id="kudos_' + blurb_id + '" style="display: none;"></div>');
			
			// retrieve a list of kudos from the work
			var work_url = 'http://archiveofourown.org/works/' + work_id + '/kudos #kudos';
			$('#kudos_' + blurb_id).load(work_url, function() {
				// check if there are kudos from the user
				var user_kudos = $('#kudos_' + blurb_id).find('[href="/users/' + username + '"]');
				
				if (user_kudos.length) {
					// highlight blurb and add work id to kudosed list
					$('#' + blurb_id).addClass('has-kudos');
					list_kudosed = ',' + work_id + list_kudosed;
				}
				else {
					// add work id to checked list
					list_checked = ',' + work_id + list_checked;
				}
			});
		}
	}
	
	// mark all works on the page as seen
	function markPageSeen() {
		
		list_seen = localStorage.getItem('kudoshistory_seen');
		
		// for each work blurb
		$('li.work.blurb').not('.marked-seen').not('.has-kudos').not('.deleted').each(function() {
			
			var work_id = $(this).attr('id').replace('work_', '');
			
			$(this).addClass('marked-seen');
			list_seen = ',' + work_id + list_seen;
		});
		
		// for each bookmark blurb
		$('li.bookmark.blurb').not('.marked-seen').not('.has-kudos').not('.deleted').each(function() {
			
			var work_link = $(this).find('h4 a:first').attr('href');
			
			// if it's not a series bookmark
			if (work_link.indexOf('series') == -1) {
				var work_id = work_link.split('/').pop();
				$(this).addClass('marked-seen');
				list_seen = ',' + work_id + list_seen;
			}
		});
		
		localStorage.setItem('kudoshistory_seen', list_seen);
	}
	
	// mark all works on the page as unseen
	function markPageUnseen() {
		
		list_seen = localStorage.getItem('kudoshistory_seen');
		
		// for each work blurb
		$('li.work.blurb').not('.deleted').each(function() {
			
			var work_id = $(this).attr('id').replace('work_', '');
			
			$(this).removeClass('marked-seen');
			list_seen = list_seen.replace(',' + work_id + ',', ',');
		});
		
		// for each bookmark blurb
		$('li.bookmark.blurb').not('.deleted').each(function() {
			
			var work_link = $(this).find('h4 a:first').attr('href');
			
			// if it's not a series bookmark
			if (work_link.indexOf('series') == -1) {
				var work_id = work_link.split('/').pop();
				$(this).removeClass('marked-seen');
				list_seen = list_seen.replace(',' + work_id + ',', ',');
			}
		});
		
		localStorage.setItem('kudoshistory_seen', list_seen);
	}
	
	// re-check the page for kudos
	function recheckKudos() {
		
		list_kudosed = localStorage.getItem('kudoshistory_kudosed');
		list_checked = localStorage.getItem('kudoshistory_checked');
		
		// for each non-kudosed work blurb
		$('li.work.blurb').not('.has-kudos').not('.deleted').each(function() {
			
			// get work id
			var work_id = $(this).attr('id').replace('work_', '');
			
			loadKudos(work_id, 'work_' + work_id, $(this));
		});
		
		// for each non-kudosed bookmark blurb
		$('li.bookmark.blurb').not('.has-kudos').not('.deleted').each(function() {
			
			// get bookmark and work ids
			var bookmark_id = $(this).attr('id');
			var work_link = $(this).find('h4 a:first').attr('href');
			
			// if it's not a series bookmark
			if (work_link.indexOf('series') == -1) {
				var work_id = work_link.split('/').pop();
				loadKudos(work_id, bookmark_id, $(this));
			}
		});
		
		function loadKudos(work_id, blurb_id, blurb) {
			// add a div to the blurb that will house the kudos
			blurb.append('<div id="kudos_' + blurb_id + '" style="display: none;"></div>');
			
			// retrieve a list of kudos from the work
			var work_url = 'http://archiveofourown.org/works/' + work_id + '/kudos #kudos';
			$('#kudos_' + blurb_id).load(work_url, function() {
				// check if there are kudos from the user
				var user_kudos = $('#kudos_' + blurb_id).find('[href="/users/' + username + '"]');
				
				if (user_kudos.length) {
					// highlight blurb and add work id to kudosed list
					$('#' + blurb_id).addClass('has-kudos');
					list_kudosed = ',' + work_id + list_kudosed;
					list_checked = list_checked.replace(',' + work_id + ',', ',');
				}
			});
		}
		
		localStorage.setItem('kudoshistory_kudosed', list_kudosed);
		localStorage.setItem('kudoshistory_checked', list_checked);
	}
	
	// check the page for bookmarks
	function checkForBookmarks() {
		
		// for each work and bookmark blurb
		$('li.work.blurb').add('li.bookmark.blurb').not('.deleted').each(function() {
			
			// get work link
			var blurb_id = $(this).attr('id');
			var work_link = $(this).find('h4 a:first').attr('href');
			
			// add a div to the blurb that will house the bookmark button
			$(this).append('<div id="bookmarked_' + blurb_id + '" style="display: none;"></div>');
			
			// retrieve the bookmark button from the work
			var work_url = 'http://archiveofourown.org' + work_link + ' a.bookmark_form_placement_open:first';
			$('#bookmarked_' + blurb_id).load(work_url, function() {
				// check if there is a bookmark from the user
				var bookmark_button_text = $('#bookmarked_' + blurb_id).find('a').text();
				
				if (bookmark_button_text.indexOf('Edit') > -1) {
					// highlight blurb
					$('#' + blurb_id).addClass('is-bookmarked');
				}
			});
		});
	}
	
	// add the seen/unseen buttons
	function addSeenButtons() {
		
		var seen_button1 = $('<li class="mark-seen"></li>').html('<a>Seen &check;</a>');
		var seen_button2 = seen_button1.clone();
		$('ul.actions').on('click', 'li.mark-seen', function() {
			list_seen = localStorage.getItem('kudoshistory_seen');
			list_seen = ',' + work_id + list_seen;
			localStorage.setItem('kudoshistory_seen', list_seen);
			$('dl.work.meta.group').addClass('marked-seen');
			seen_button1.replaceWith(unseen_button1);
			seen_button2.replaceWith(unseen_button2);
		});
		
		var unseen_button1 = $('<li class="mark-unseen"></li>').html('<a>Unseen &cross;</a>');
		var unseen_button2 = unseen_button1.clone();
		$('ul.actions').on('click', 'li.mark-unseen', function() {
			list_seen = localStorage.getItem('kudoshistory_seen');
			list_seen = list_seen.replace(',' + work_id + ',', ',');
			localStorage.setItem('kudoshistory_seen', list_seen);
			$('dl.work.meta.group').removeClass('marked-seen');
			unseen_button1.replaceWith(seen_button1);
			unseen_button2.replaceWith(seen_button2);
		});
		
		if (is_seen == -1) {
			$('li.bookmark').after(seen_button1);
			$('#new_kudo').parent().after(seen_button2);
		}
		else {
			$('li.bookmark').after(unseen_button1);
			$('#new_kudo').parent().after(unseen_button2);
		}
	}
		
	// attach the menu
	function addSeenMenu() {
		
		// get the header menu
		var header_menu = $('ul.primary.navigation.actions');
		
		// create and insert menu button
		var seen_menu = $('<li class="dropdown"></li>').html('<a>Seen works</a>');
		header_menu.find('li.search').before(seen_menu);
		
		// create and append dropdown menu
		var drop_menu = $('<ul class="menu dropdown-menu"></li>');
		seen_menu.append(drop_menu);
		
		// create button - all works
		var button_all_works = $('<li></li>').html('<a style="padding: 0.5em 0.5em 0.25em; text-align: center; font-weight: bold;">&mdash; For all works on this page: &mdash;</a>');
		
		// create button - mark page as seen
		var button_page_seen = $('<li></li>').html('<a>Mark as seen</a>');
		button_page_seen.click(function() {markPageSeen();});
		
		// create button - mark page as unseen
		var button_page_unseen = $('<li></li>').html('<a>Unmark as seen</a>');
		button_page_unseen.click(function() {markPageUnseen();});
		
		// create button - re-check page for kudos
		var button_recheck_kudos = $('<li></li>').html('<a>Re-check for kudos</a>');
		button_recheck_kudos.click(function() {recheckKudos();});
		
		// create button - check page for bookmarks
		var button_check_bookmarks = $('<li></li>').html('<a>Check for bookmarks</a>');
		button_check_bookmarks.click(function() {checkForBookmarks();});
		
		// create button - settings
		var button_settings = $('<li></li>').html('<a style="padding: 0.5em 0.5em 0.25em; text-align: center; font-weight: bold;">&mdash; Settings (click to change): &mdash;</a>');
		
		// create button - don't hide seen works
		var button_hide_no = $('<li class="hide-no"></li>').html('<a>Hide seen works: NO</a>');
		drop_menu.on('click', 'li.hide-no', function() {
			localStorage.setItem('kudoshistory_hide', 'yes');
			hide_seen = 1;
			addCss(true);
			button_hide_no.replaceWith(button_hide_yes);
		});
		
		// create button - hide seen works
		var button_hide_yes = $('<li class="hide-yes"></li>').html('<a>Hide seen works: YES</a>');
		drop_menu.on('click', 'li.hide-yes', function() {
			localStorage.setItem('kudoshistory_hide', 'collapse');
			hide_seen = 2;
			addCss(true);
			button_hide_yes.replaceWith(button_hide_collapse);
		});
		
		// create button - collapse seen works
		var button_hide_collapse = $('<li class="hide-collapse"></li>').html('<a>Hide seen works: COLLAPSE</a>');
		drop_menu.on('click', 'li.hide-collapse', function() {
			localStorage.setItem('kudoshistory_hide', 'no');
			hide_seen = 0;
			addCss(true);
			button_hide_collapse.replaceWith(button_hide_no);
		});
		
		// create button - mark as seen on open
		var button_auto_yes = $('<li class="auto-yes"></li>').html('<a>Mark as seen on open: YES</a>');
		drop_menu.on('click', 'li.auto-yes', function() {
			localStorage.setItem('kudoshistory_autoseen', 'no');
			auto_seen = false;
			button_auto_yes.replaceWith(button_auto_no);
		});
		
		// create button - don't mark as seen on open
		var button_auto_no = $('<li class="auto-no"></li>').html('<a>Mark as seen on open: NO</a>');
		drop_menu.on('click', 'li.auto-no', function() {
			localStorage.setItem('kudoshistory_autoseen', 'yes');
			auto_seen = true;
			button_auto_no.replaceWith(button_auto_yes);
		});
		
		// append buttons to the dropdown menu
		drop_menu.append(button_all_works, button_page_seen, button_page_unseen, button_recheck_kudos, button_check_bookmarks, button_settings);
		
		switch (hide_seen) {
			case 1:
				drop_menu.append(button_hide_yes);
				break;
			case 2:
				drop_menu.append(button_hide_collapse);
				break;
			default:
				drop_menu.append(button_hide_no);
		}
		
		if (auto_seen) {
			drop_menu.append(button_auto_yes);
		}
		else {
			drop_menu.append(button_auto_no);
		}
	}
	
	// add css rules to page head
	function addCss(change) {
		var style = $('style');
		var css_highlight = '.has-kudos,\
			.has-kudos.marked-seen {background: url("http://i.imgur.com/qLvF6Md.png") left no-repeat, url("http://i.imgur.com/qdA6ylN.png") left repeat-y; padding-left: 70px !important;}\
			.marked-seen {background: url("http://i.imgur.com/qdA6ylN.png") left repeat-y; padding-left: 70px !important;}\
			.is-bookmarked {background: url("http://i.imgur.com/PwBH9aC.png") right repeat-y; padding-right: 70px !important;}\
			.has-kudos.is-bookmarked,\
			.has-kudos.marked-seen.is-bookmarked {background: url("http://i.imgur.com/qLvF6Md.png") left no-repeat, url("http://i.imgur.com/qdA6ylN.png") left repeat-y, url("http://i.imgur.com/PwBH9aC.png") right repeat-y;}\
			.marked-seen.is-bookmarked {background: url("http://i.imgur.com/qdA6ylN.png") left repeat-y, url("http://i.imgur.com/PwBH9aC.png") right repeat-y;}';
		var css_hide = 'li.has-kudos,\
			li.marked-seen {display: none !important;}';
		var css_collapse = 'li.has-kudos h6.landmark.heading,\
			li.has-kudos > ul,\
			li.has-kudos blockquote.userstuff.summary,\
			li.has-kudos dl.stats,\
			li.has-kudos .header .fandoms.heading,\
			li.marked-seen h6.landmark.heading,\
			li.marked-seen > ul,\
			li.marked-seen blockquote.userstuff.summary,\
			li.marked-seen dl.stats,\
			li.marked-seen .header .fandoms.heading {display: none !important;}\
			li.has-kudos ul.required-tags,\
			li.marked-seen ul.required-tags {opacity: 0.6;}\
			li.has-kudos ul.required-tags li + li,\
			li.marked-seen ul.required-tags li + li {position: absolute; left: 56px; top: 0px;}\
			li.has-kudos ul.required-tags li + li + li,\
			li.marked-seen ul.required-tags li + li + li {left: 28px;}\
			li.has-kudos ul.required-tags li + li + li + li,\
			li.marked-seen ul.required-tags li + li + li + li {left: 84px; top: 0px;}\
			li.has-kudos .header,\
			li.marked-seen .header {min-height: 27px;}\
			li.has-kudos .header .heading,\
			li.marked-seen .header .heading {margin: 0.375em 5.25em 0px 121px;}';

		if (!style.length) {
			style = $('<style type="text/css"></style>').appendTo($('head'));
		}
		
		if (change) {
			switch (hide_seen) {
				case 1:
					style.append(css_hide);
					break;
				case 2:
					style.html(style.html().replace(css_hide, ''));
					style.append(css_collapse);
					break;
				default:
					style.html(style.html().replace(css_collapse, ''));
			}
		}
		else {
			switch (hide_seen) {
				case 1:
					style.append(css_highlight, css_hide);
					break;
				case 2:
					style.append(css_highlight, css_collapse);
					break;
				default:
					style.append(css_highlight);
			}
		}
	}
})(jQuery);