coderlex / Фильтр для ficbook.net

// ==UserScript==
// @name Фильтр для ficbook.net
// @description Скрывает всякую мелочь, слэш и выброшенные вами произведения на фикбуке.
// @author coderlex
// @license MIT
// @version 1.0.1
// @include http://ficbook.net/*
// @include https://ficbook.net/*
// @grant none
// ==/UserScript==
// Crossbrowsering~ closure (opera, ie)
(function (window, undefined) {  // Smth strange...
	var w
	if (typeof unsafeWindow != 'undefined') {
		w = unsafeWindow
	} else {
		w = window
	}
	// a function that loads jQuery and calls a callback function when jQuery has finished loading
	function requireJQuery(callback) {
		var script = document.createElement('script')
		script.setAttribute('src', '//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js')
		script.addEventListener('load', function() {
			var script = document.createElement('script')
			script.textContent = 'window.jQ=jQuery.noConflict(true);(' + callback.toString() + ')();'
			document.body.appendChild(script)
		}, false)
		document.body.appendChild(script)
	}
	// Stop executing in frames
	if (w.self != w.top) {
		return
	}
	// Additional check
	if (/ficbook.net(\/home)?\/collections/.test(w.location.href)) {
		requireJQuery(function() {
			function setHiddenAuthors(authorsId) {
				localStorage.setItem(
					'ficbookFilter.hiddenAuthors',
					JSON.stringify(authorsId)
				)
			}
			function setHiddenWritings(writingsId) {
				localStorage.setItem(
					'ficbookFilter.hiddenWritings',
					JSON.stringify(writingsId)
				)
			}
			function getHiddenAuthors() {
				var str = localStorage.getItem('ficbookFilter.hiddenAuthors')
				return str ? JSON.parse(str) : []
			}
			function getHiddenWritings() {
				var str = localStorage.getItem('ficbookFilter.hiddenWritings')
				return str ? JSON.parse(str) : []
			}
			function updateMargins() {
				$('.ficbook-filters-hidden-msg + table').each(function() {
                    $(this).prev().css('margin-bottom', $(this).is(':visible') ? '20px' : 'auto')
				})
			}
			// Create export button
			var $exportBtn = $('<div/>')
				.css({
					position: 'fixed',
					bottom: '20px',
					right: '80px',
					color: 'white',
					background: 'rgba(0, 0, 0, 0.52)',
					'border-radius': '3px',
					width: '25px',
					'text-align': 'center',
					height: '24px',
					'line-height': '24px',
					cursor: 'pointer',
					'font-size': '18px'
				})
				.attr('title', 'Экспортировать бан-список')
				.html('E')
				.appendTo(document.body)
			$exportBtn.click(function() {
				var data = JSON.stringify({
					authors:  getHiddenAuthors(),
					writings: getHiddenWritings()
				})
				var $a = $('<a/>')
					.attr('href', 'data:text/plain,' + data)
					.attr('download', 'ficbook-filters.json')
					.appendTo(document.body)
				$a[0].click()
				$a.remove()
			})
			// Create import button
			var $fileInput = $('<input type="file"/>')
				.css({
					position: 'absolute',
					top: '-10000px',
					left: '-10000px'
				})
				.appendTo(document.body)
			var $importBtn = $exportBtn.clone()
				.css({
					right: '110px'
				})
				.attr('title', 'Импортировать бан-список')
				.html('I')
				.appendTo(document.body)
			$importBtn.click(function() {
				$fileInput.click()
			})
			$fileInput.change(function() {
				try {
					var fileReader = new FileReader()
					fileReader.readAsText(this.files[0])
					fileReader.onloadend = function() {
						try {
							var json = JSON.parse(this.result)
						}
						catch (e) {
							alert('Ошибка. Файл бан-списка поврежден.\n' +
								'По умолчанию это обычно "ficbook-filters.json".\n' +
								'Может быть, вы выбрали какой-то другой файл?')
							return
						}
						setHiddenWritings(json.writings)
						setHiddenAuthors(json.authors)
						alert('Импортировано ' + json.writings.length +
							' произведений и ' + json.authors.length + ' авторов.\n' +
							'Обновите страницу чтобы применить фильтры немедленно.')
					}
				}
				catch (e) {
					alert('Ошибка. Файл бан-списка поврежден.')
					console.error(e.toString())
				}
			})
			// Load hidden authors and writings
			var hiddenAuthors = getHiddenAuthors()
			var hiddenWritings = getHiddenWritings()
			// Hide writings
			$('.fanfic_thumb').each(function() {
				var $title = $('a.title', this),
					title = $title.text(),
					writingId = parseInt($title.attr('href').match(/\/(\d+)$/)[1], 10),
					text = $('b:eq(1)', this).closest('small').text(),
					pageCount = parseInt(text.match(/(\d+)\s+страниц/)[1]),
					slash = text.indexOf('(яой)') >= 0,
					writingHidden = hiddenWritings.indexOf(writingId) >= 0,
					$author = $('>tbody>tr:eq(1)>td:eq(0) a:eq(0)', this),
					authorId = parseInt($author.attr('href').match(/\/(\d+)$/)[1], 10),
					authorHidden = hiddenAuthors.indexOf(authorId) >= 0,
					$thumb = $(this)
				function hideThisFic() {
					var $hidden = $('<div/>')
						.css({
							color: '#888'
						})
						.addClass('ficbook-filters-hidden-msg')
						.html('Отфильтровано <a href="' + $title.attr('href') + '">"'
							+ title + '"</a> от <a href="' + $author.attr('href') +
							'">' + $author.text() + '</a>.')
					var $resurrectBtn = $('<span>&#9760;</span>')
						.attr('title', 'Да ВОССТАНЬ! (Воскрешает отфильтрованный фанф)')
						.css({
							cursor: 'pointer',
							color: '#007915',
							display: 'inline-block',
							background: '#fff',
							'border-radius': '10px',
							height: '20px',
							'line-height': '20px',
							padding: '0 5px',
							'margin-left': '5px'
						})
						.appendTo($hidden)
					$thumb.parent().closest('table').hide().after($hidden)
					$resurrectBtn.click(function() {
						if (authorHidden) {
                            hiddenAuthors = getHiddenAuthors() // could be updated on the other tab
							hiddenAuthors.splice(hiddenAuthors.indexOf(authorId), 1)
							setHiddenAuthors(hiddenAuthors)
						}
						if (writingHidden) {
                            hiddenWritings = getHiddenWritings() // could be updated on the other tab
							hiddenWritings.splice(hiddenWritings.indexOf(writingId), 1)
							setHiddenWritings(hiddenWritings)
						}
						var $msg = $(this).closest('.ficbook-filters-hidden-msg')
						$msg.prev().show()
						$msg.remove()
						return false
					})
				}
				if (pageCount < 30 || slash || writingHidden || authorHidden)
					hideThisFic()
				// Add removing writing button
				var $rmWritingBtn = $('<span/>')
					.css({
						cursor: 'pointer',
						color: 'white',
						'font-weight': 'bold',
						display: 'inline-block',
						background: 'rgb(136, 1, 1)',
						'border-radius': '10px',
						height: '20px',
						'line-height': '20px',
						padding: '0 5px',
						'margin-left': '5px'
					})
					.attr('title', 'Забанить это произведение')
					.html('&#10006; W')
				$title.parent().append($rmWritingBtn)
				$rmWritingBtn.click(function() {
                    hiddenWritings = getHiddenWritings() // could be updated on the other tab
					hiddenWritings.push(writingId)
					setHiddenWritings(hiddenWritings)
					hideThisFic()
					return false
				})
				// Add removing author button
				var $rmAuthorBtn = $rmWritingBtn.clone()
					.attr('title', 'Забанить ВСЕ произведения этого автора')
					.html('&#10006; A')
				$title.parent().append($rmAuthorBtn)
				$rmAuthorBtn.click(function() {
                    hiddenAuthors = getHiddenAuthors() // could be updated on the other tab
					hiddenAuthors.push(authorId)
					setHiddenAuthors(hiddenAuthors)
					hideThisFic()
					return false
				})
			})
			// Some decoration
			updateMargins()
		})
	}
})(window)