Greasy Fork is available in English.

FanFictionNavigator

Mark and hide fanfics or authors

2017-08-16 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

// ==UserScript==
// @name        FanFictionNavigator
// @name:ru     FanFictionNavigator
// @namespace   window
// @description:en  Mark and hide fanfics or authors
// @description:ru  Выделяет цветом/скрывает фанфики или авторов
// @include     https://ficbook.net/*
// @include     http://ficbook.net/*
// @include     https://www.fanfiction.net/*
// @include     http://www.fanfiction.net/*
// @include     https://archiveofourown.org/*
// @include     http://archiveofourown.org/*
// @include     https://tbooklist.org/*

// @require     https://code.jquery.com/jquery-1.7.2.min.js

// @version     10
// @grant       none
// @description Mark and hide fanfics or authors
// ==/UserScript==

// Fics:
const FIC_LIKED = 0
const FIC_DISLIKED = 1
const FIC_MARKED = 2
const FIC_CALIBRE = 3

// Authors:
const AUTHOR_LIKED = 0
const AUTHOR_DISLIKED = 1

const COLOR_LIKED = '#C4FFCA';
const COLOR_DISLIKED = '#FCB0B0';
const COLOR_MARKED = '#CCCCCC';
const COLOR_CALIBRE = '#F1D173';
const COLOR_CLEARED = '#FFF';
const COLOR_FB_CLEAR = '#FFF';

//  Underscore.js 1.4.4. Inline because github site isn't approved for @require
;(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index<t.index?-1:1}),"value")};var F=function(n,t,r,e){var u={},i=k(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return F(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return F(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n","	":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);

// prevent conflicts with websites' jQuery version
this.ffn$ = this.jQuery = jQuery.noConflict(true);

var db = JSON.parse(localStorage.getItem("FFLikerAA") || '{}');
db.options = db.options || {};
db.version = db.version || '0.2';


//
// APP
//


// Main
var Application = function Application(options) {
	var a = {};
	var options  = options || {};

	if(!options.namespace) { throw new Error("namespace is required"); }
	if(!options.db) { throw new Error("database object is required"); }

	a.namespace = options.namespace;
	var db = options.db;
	db[a.namespace] = db[a.namespace] || { fic: {}, author:{} };

	a.collection = [];

	a.color = {
		link_default: ffn$("ol.work.index.group > li:first a:first").css("color"),
		like_link:'',
		like_background:'',
		dislike_link:'',
		dislike_background:'',
	}

	a.save = function(type,id,value){
		if(type == "fic" || type == "author") {
			a.saveNameSpaced(type,id,value);
		} else {
			if(value === "clear") {
				delete db[type][id];
			} else {
				db[type][id] = value;
			}
			localStorage.setItem("FFLikerAA", JSON.stringify(db))
		}
	}

	a.saveNameSpaced = function(type,id,value){
		if(value === "clear") {
			delete db[a.namespace][type][id];
		} else {
			db[a.namespace][type][id] = value;
		}
		localStorage.setItem("FFLikerAA", JSON.stringify(db))
	}


	a.author = {};

		a.author.get = function(id){
			return db[a.namespace]["author"][id];
		}

		a.author.like = function(id) {
			a.save("author",id,AUTHOR_LIKED);

			_.each(a.author.getFics(id), function(story){
				story.author = AUTHOR_LIKED;
				story.like_author();
			});
		}

		a.author.dislike = function(id) {
			a.save("author",id,AUTHOR_DISLIKED);
			//ga('set', 'metric3', 1);

			_.each(a.author.getFics(id), function(story){
				story.author = AUTHOR_DISLIKED;
				story.dislike_author();
			});
		}
   
		a.author.clear = function(id) {
			a.save("author",id,"clear");

			_.each(a.author.getFics(id), function(story){
				story.author = '';
				story.clear_author();
			});
		}

		a.author.getFics = function(id) {
			return _.filter(a.collection,function(story){
				return story.authorId() == id;
			})
		}

	a.fic = {};

		a.fic.get = function(id) {
			return db[a.namespace]["fic"][id];
		}

		a.fic.like = function(id) {
			a.save("fic",id,FIC_LIKED);

			var story = _.find(a.collection,function(story){
				return story.ficId() == id;
			});

			story.fic = FIC_LIKED;
			story.like_story();
		}

		a.fic.dislike = function(id) {
			a.save("fic",id,FIC_DISLIKED);
			var story = _.find(a.collection,function(story){
				return story.ficId() == id;
			});
			story.fic = FIC_DISLIKED;
			story.dislike_story();
		}

        a.fic.mark = function(id) {
            a.save("fic",id,FIC_MARKED);
            var story = _.find(a.collection,function(story){
				return story.ficId() == id;
			});
            story.fic = FIC_MARKED;
            story.mark_story();
        }

        a.fic.calibre = function(id) {
            a.save("fic",id,FIC_CALIBRE);
            var story = _.find(a.collection,function(story){
				return story.ficId() == id;
			});
            story.fic = FIC_CALIBRE;
            story.calibre_story();
        }


		a.fic.clear = function(id) {
			a.save("fic",id,"clear");
			var story = _.find(a.collection,function(story){
				return story.ficId() == id;
			});
			story.fic = '';
			story.clear_story();
		}

	a.options = function(name, value) {

		if(!name) { throw new Error("name is required. what option are you looking for?"); }

		if(typeof value !== "undefined") {
			a.save("options",name,value)
			return false;
		} else { 
			return db.options[name];
		}
	}

	return a;
}

var Story = function(options) {

	var a = {};
	var options  = options || {};

	if(!options.instance) { throw new Error("instance of this is required"); }
	if(!options.namespace) { throw new Error("namespace is required"); }

	var _this = ffn$(options.instance);

	a["default"] = {
		template: function() {
			var template =	'<div class="new_like_actions" style="margin:0px 0px 0px 20px; font-size:11px;">'+

								'Story: <a href="" class="like_story"><font color="'+COLOR_LIKED+'">Like</font></a> | '+
								'<a href="" class="dislike_story"><font color="'+COLOR_DISLIKED+'">Dislike</font></a> | '+
    							'<a href="" class="mark_story"><font color="'+COLOR_MARKED+'">Mark</font></a> | '+
    							'<a href="" class="calibre_story"><font color="'+COLOR_CALIBRE+'">Calibre</font></a> | '+
								'<a href="" class="clear_story" style="color:blue;">Clear</a>'+

								'   Author: <a href="" class="like_author" style="color:blue;">Like</a> | '+
								'<a href="" class="dislike_author" style="color:blue;">Dislike</a> | '+
								'<a href="" class="clear_author" style="color:blue;">Clear</a>'+

							'</div>';
			return template;
		},
		addActions: function() {
			var instance = this;
			_this.append(this.template());

			_this.find('.new_like_actions .like_author').click(function(){ app.author.like(instance.authorId()); return false; });
			_this.find('.new_like_actions .dislike_author').click(function(){ app.author.dislike(instance.authorId()); return false; });
			_this.find('.new_like_actions .clear_author').click(function(){ app.author.clear(instance.authorId()); return false; });

			_this.find('.new_like_actions .like_story').click(function(){ app.fic.like(instance.ficId()); return false; });
			_this.find('.new_like_actions .dislike_story').click(function(){ app.fic.dislike(instance.ficId()); return false; });
    		_this.find('.new_like_actions .mark_story').click(function(){ app.fic.mark(instance.ficId()); return false; });
    		_this.find('.new_like_actions .calibre_story').click(function(){ app.fic.calibre(instance.ficId()); return false; });
			_this.find('.new_like_actions .clear_story').click(function(){ app.fic.clear(instance.ficId()); return false; });
		},
		hide: function() {
			_this.hide();
		},
		set_story: function(){
            switch(this.fic){
            case FIC_LIKED: 
				_this.css('background-color',COLOR_LIKED);
				this.$fic.css('font-weight','900')
                break;
			case FIC_DISLIKED: 
				_this.css('background-color',COLOR_DISLIKED);
				this.$fic.css('font-weight','900')
                break;
            case FIC_MARKED:
    			_this.css('background-color',COLOR_MARKED);
				this.$fic.css('font-weight','900')
                break;
            case FIC_CALIBRE:
    			_this.css('background-color',COLOR_CALIBRE);
				this.$fic.css('font-weight','900')
                break;
			}
		},
		set_author: function() {
/*			if(this.fic === true){
				_this.css('background-color',COLOR_LIKED);
			}
			if(this.fic === false){
				_this.css('background-color',COLOR_DISLIKED);
			}*/

			if(this.author === AUTHOR_LIKED) {
				this.$author.css('color','green').css('font-weight','900')
				if(typeof this.fic === "undefined") {
					_this.css('background-color',COLOR_LIKED);
				}
			}
			if(this.author === AUTHOR_DISLIKED) {
				this.$author.css('color','red').css('font-weight','900')
				if(typeof this.fic === "undefined") {
					_this.css('background-color',COLOR_DISLIKED);
				}
			}
		}
	};

// Specific sites overrides

	a["www.fanfiction.net"] = {
		$author: _this.find('a[href^="/u"]:first'),
		$fic: _this.find('a[href^="/s"]:first'),
		authorId: function() {
            if (window.location.pathname.split("/")[1] === "u") {
                return window.location.pathname.split("/")[2]
            } else {
        		return this.$author.attr('href').split('/')[2];
            }
		},
		ficId: function() {
            if (this.$fic.length === 0) {
                return window.location.pathname.split("/")[2];
            } else {
                return this.$fic.attr('href').split('/')[2];
            }
		},

    	hide: function() {
            if (! window.location.pathname.split("/")[1].match("^s$|^u$")) _this.hide();  // do not hide story header when reading
		},
		like_story: function(){
			_this.css('background-color',COLOR_LIKED);
			this.$fic.css('font-weight','900');
		},
		dislike_story: function(){
			_this.css('background-color',COLOR_DISLIKED)
			this.$fic.css('font-weight','900');
		},
    	mark_story: function(){
			_this.css('background-color',COLOR_MARKED)
			this.$fic.css('font-weight','900');
		},
        calibre_story: function(){
			_this.css('background-color',COLOR_CALIBRE)
			this.$fic.css('font-weight','900');
		},

		clear_story: function(){

			if(this.author === 0) {
				_this.css('background-color',COLOR_LIKED);
			} else if(this.author === 1) {
				_this.css('background-color',COLOR_DISLIKED);
			} else {
				_this.css('background-color',COLOR_CLEARED);
			}
			this.$fic.css('font-weight','normal');

		},
		like_author: function(){

			if(this.fic !== FIC_DISLIKED) {
				_this.css('background-color',COLOR_LIKED)
			}
			this.$author.css('font-weight','900');

		},
		dislike_author: function(){

			if(this.fic !== FIC_LIKED) {
				_this.css('background-color',COLOR_DISLIKED)
			}
			this.$author.css('font-weight','900');

		},
    	clear_author: function(){
            switch(this.fic){
            case FIC_LIKED: 
				_this.css('background-color',COLOR_LIKED);
				this.$fic.css('font-weight','900')
                break;
			case FIC_DISLIKED: 
				_this.css('background-color',COLOR_DISLIKED);
				this.$fic.css('font-weight','900')
                break;
            case FIC_MARKED:
    			_this.css('background-color',COLOR_MARKED);
				this.$fic.css('font-weight','900')
                break;
            case FIC_CALIBRE:
    			_this.css('background-color',COLOR_CALIBRE);
				this.$fic.css('font-weight','900')
                break;
            default:
    			_this.css('background-color',COLOR_CLEARED);
			}
			this.$author.css('color',app.color.link_default).css('font-weight','normal');

		}

	}

//

	a["archiveofourown.org"] = {
    	$author: _this.find('a[href^="/users/"]:first'),
		$fic: _this.find('a[href^="/works/"]:first'),
		authorId: function() {
			return this.$author.attr('href').split('/')[2];
		},
        ficId: function() {
            if (this.$fic.length === 0) {
                return window.location.pathname.split("/")[2];
            } else {
                return this.$fic.attr('href').split('/')[2];
            }
		},
		like_story: function(){

			_this.css('background-color',COLOR_LIKED);
			this.$fic.css('font-weight','900');
			
		},
		dislike_story: function(){
			
			_this.css('background-color',COLOR_DISLIKED)
			this.$fic.css('font-weight','900');

		},
    	mark_story: function(){
			_this.css('background-color',COLOR_MARKED)
			this.$fic.css('font-weight','900');
		},
        calibre_story: function(){
			_this.css('background-color',COLOR_CALIBRE)
			this.$fic.css('font-weight','900');
		},
		clear_story: function(){

			if(this.author === 0) {
				_this.css('background-color',COLOR_LIKED);
			} else if(this.author === 1) {
				_this.css('background-color',COLOR_DISLIKED);
			} else {
				_this.css('background-color',COLOR_CLEARED);
			}
			this.$fic.css('font-weight','normal');

		},
		like_author: function(){

			if(this.fic !== 1) {
				_this.css('background-color',COLOR_LIKED)
			}
			this.$author.css('font-weight','900');

		},
		dislike_author: function(){

			if(this.fic !== 0) {
				_this.css('background-color',COLOR_DISLIKED)
			}
			this.$author.css('font-weight','900');

		},
    	clear_author: function(){
            switch(this.fic){
            case FIC_LIKED: 
				_this.css('background-color',COLOR_LIKED);
				this.$fic.css('font-weight','900')
                break;
			case FIC_DISLIKED: 
				_this.css('background-color',COLOR_DISLIKED);
				this.$fic.css('font-weight','900')
                break;
            case FIC_MARKED:
    			_this.css('background-color',COLOR_MARKED);
				this.$fic.css('font-weight','900')
                break;
            case FIC_CALIBRE:
    			_this.css('background-color',COLOR_CALIBRE);
				this.$fic.css('font-weight','900')
                break;
            default:
    			_this.css('background-color',COLOR_CLEARED);
			}
			this.$author.css('color',app.color.link_default).css('font-weight','normal');
        },

        hide:function(){
            if (window.location.pathname.split("/")[3]!=="chapters") {
                _this.hide()
            }
        }
	}

//

    a["ficbook.net"] = {
        $author: _this.find('a[href^="/authors"]:first'),
        $fic: _this.find('a[href^="/readfic"]:first'),
		authorId: function() {
			return this.$author.attr('href').split('/')[2];
		},
        ficId: function() {
            if (this.$fic.length === 0) {
                return window.location.pathname.split("/")[2];
            } else {
                return this.$fic.attr('href').split('/')[2];
            }
		},

		like_story: function(){

			_this.css('background-color',COLOR_LIKED);
			this.$fic.css('font-weight','900');
			
		},
		dislike_story: function(){
			
			_this.css('background-color',COLOR_DISLIKED)
			this.$fic.css('font-weight','900');

		},
    	mark_story: function(){
			_this.css('background-color',COLOR_MARKED)
			this.$fic.css('font-weight','900');
		},
        calibre_story: function(){
			_this.css('background-color',COLOR_CALIBRE)
			this.$fic.css('font-weight','900');
		},
		clear_story: function(){

			if(this.author === true) {
				_this.css('background-color',COLOR_LIKED);
			} else if(this.author === false) {
				_this.css('background-color',COLOR_DISLIKED);
			} else {
				_this.css('background-color',COLOR_FB_CLEAR);
			}
			this.$fic.css('font-weight','normal');

		},
		like_author: function(){

			if(this.fic !== false) {
				_this.css('background-color',COLOR_LIKED)
			}
			this.$author.css('font-weight','900');

		},
		dislike_author: function(){

			if(this.fic !== true) {
				_this.css('background-color',COLOR_DISLIKED)
			}
			this.$author.css('font-weight','900');

		},
		clear_author: function(){

			if(this.fic === true) {
				_this.css('background-color',COLOR_LIKED);
			} else if(this.fic === false) {
				_this.css('background-color',COLOR_DISLIKED);
			} else {
				_this.css('background-color',COLOR_FB_CLEAR);
			}
			this.$author.css('font-weight','normal');

		},
        hide:function(){

            if (window.location.pathname.split("/")[1]!=="readfic") {
                _this.parent().hide()
            }
        }
	}

//

        a["tbooklist.org"] = {
        $author: _this.find('a[href^="https://tbooklist.org/authors"]:first'),
        $fic: _this.find('a[href^="https://tbooklist.org/books"]:first'),
		authorId: function() {
            if (this.$author.length === 0) {
                return 0;
            } else {
                return this.$author.attr('href').split('/')[4];
            }
		},
        ficId: function() {
            if (window.location.pathname.split("/")[1] === "books") {
                return window.location.pathname.split("/")[2]
            }
            if (this.$fic.length === 0) {
                return 0;
            } else {
                return this.$fic.attr('href').split('/')[4];
            }
		},

		like_story: function(){

			_this.css('background-color',COLOR_LIKED);
			this.$fic.css('font-weight','900');
			
		},
		dislike_story: function(){
			
			_this.css('background-color',COLOR_DISLIKED)
			this.$fic.css('font-weight','900');

		},
    	mark_story: function(){
			_this.css('background-color',COLOR_MARKED)
			this.$fic.css('font-weight','900');
		},
        calibre_story: function(){
			_this.css('background-color',COLOR_CALIBRE)
			this.$fic.css('font-weight','900');
		},
		clear_story: function(){

			if(this.author === true) {
				_this.css('background-color',COLOR_LIKED);
			} else if(this.author === false) {
				_this.css('background-color',COLOR_DISLIKED);
			} else {
				_this.css('background-color',COLOR_FB_CLEAR);
			}
			this.$fic.css('font-weight','normal');

		},
		like_author: function(){

			if(this.fic !== false) {
				_this.css('background-color',COLOR_LIKED)
			}
			this.$author.css('font-weight','900');

		},
		dislike_author: function(){

			if(this.fic !== true) {
				_this.css('background-color',COLOR_DISLIKED)
			}
			this.$author.css('font-weight','900');

		},
		clear_author: function(){

			if(this.fic === true) {
				_this.css('background-color',COLOR_LIKED);
			} else if(this.fic === false) {
				_this.css('background-color',COLOR_DISLIKED);
			} else {
				_this.css('background-color',COLOR_FB_CLEAR);
			}
			this.$author.css('font-weight','normal');

		},
        hide:function(){
            // do not hide when viewing fanfic details
            if(window.location.pathname.split("/")[1] !== "books") { 
                _this.hide()
            }
        }
	}

	var b = ffn$.extend({}, a["default"], a[options.namespace]);
	b.fic = app.fic.get(b.ficId());

	b.author = app.author.get(b.authorId());
    // do not show liker links if ficid or authorid are undefined (tweak for tbooklist.org)
    if (b.ficId() != 0 && b.authorId() != 0) {
    	b.addActions();
    }
	b.set_story();
	b.set_author();

	//hide
	if((app.options("hide_dislikes") == true && (b.fic === FIC_DISLIKED || b.author === AUTHOR_DISLIKED)) || 
       (app.options("hide_likes") == true && (b.fic === FIC_LIKED || b.author === AUTHOR_LIKED)) ||
       (app.options("hide_marked") == true && b.fic === FIC_MARKED) ||
       (app.options("hide_calibre") == true && b.fic === FIC_CALIBRE)){ 
//		if(b.fic !== true && b.author) { // for those liked fics and unliked authors
			b.hide();
//		}
	}	

	return b;

}


var app  = new Application({namespace:document.location.host, db: db});

// Adding action links and navigation shortcuts to pages

if (window.location.hostname === "www.fanfiction.net") {

    // adding hotkeys
    var Next = ffn$("a:contains('Next »')")
    var Prev = ffn$("a:contains('« Prev')")
    document.addEventListener('keydown', function(e){
  		switch (e.keyCode)
        {
    	    case 37: if (typeof(Prev[0])!=='undefined') {window.location.href = Prev[0]};break;
      		case 39: if (typeof(Next[0])!=='undefined') {window.location.href = Next[0]};break;
      	}
    }, false);
    // links in list
    ffn$(".z-list").each(function(){
//        console.log(this)
    	var story = new Story({ namespace: app.namespace, instance: this });
    	app.collection.push(story);
    });

    // links on reading page
    ffn$("div#profile_top").each(function(){
    	var story = new Story({ namespace: app.namespace, instance: this });
    	app.collection.push(story);
    });

    // hide/show options
    ffn$('div#content_wrapper_inner').after(
        '<div class="liker_script_options" style="padding:5px; border:1px solid #333399; margin-bottom:5px; background:#D8D8FF;">'+
    	'<b>Liker Options:</b> '+
    	'</div>'
    );


}

if (window.location.hostname === "archiveofourown.org") {
    // adding hotkeys
    var Next = ffn$("a:contains('Next →')")
    var Prev = ffn$("a:contains('← Previous')")
    document.addEventListener('keydown', function(e){
   		switch (e.keyCode)
        {
    	    case 37: if (typeof(Prev[0])!=='undefined') {window.location.href = Prev[0]};break;
      		case 39: if (typeof(Next[0])!=='undefined') {window.location.href = Next[0]};break;
    	}
    }, false);
    // in list
    ffn$("ol.work.index.group > li").each(function(){
    	var story = new Story({ namespace: app.namespace, instance: this });
    	app.collection.push(story);
    });
    // on reading page
    ffn$("div.preface.group").each(function(){
//        console.log(this);
    	var story = new Story({ namespace: app.namespace, instance: this });
    	app.collection.push(story);
    });
    // hide/show options
    ffn$('div.navigation.actions.module').after(
    	'<div class="liker_script_options" style="padding:5px; border:1px solid #333399; margin-bottom:5px; background:#D8D8FF;">'+
    	'<b>Liker Options:</b> '+
    	'</div>'
    );
}

if (window.location.hostname === "ficbook.net") {
    // on reading page
    if (window.location.pathname.split("/")[1]==="readfic"){
//        ffn$("div.row.hat-row").not(".hat-title").each(function() {
        ffn$("div.row.hat-row > ul.list-unstyled").each(function() {
//            console.log(this)
            var story = new Story({
                namespace: app.namespace,
                instance: this
            });
            app.collection.push(story);
        });
    }
    // in search
    if (window.location.pathname.split("/")[1]==="find"){
        ffn$(".description").each(function() {
        //    console.log(this)
            var story = new Story({
                namespace: app.namespace,
                instance: this
            });
          
            app.collection.push(story);
            ffn$(this).append('<button type="button" class="btn btn-primary js-mark-readed" data-fanfic-id="'+ story.ficId() +'"><i class="icon-checkbox-unchecked2"></i>Пометить как прочитаное</button>')
        });
        // add hotkeys
        var Next = ffn$("a[aria-label='Следующая']")
        var Prev = ffn$("a[aria-label='Предыдущая']")
        document.addEventListener('keydown', function(e){
       		switch (e.keyCode)
            {
        	    case 37: window.location.href = Prev[0];break;
        		case 39: window.location.href = Next[0];break;
        	}
        }, false);
    }
    // hide/show options
    ffn$('section.content-section').after(
    	'<div class="liker_script_options" style="padding:5px; border:1px solid #333399; margin-bottom:5px; background:#D8D8FF;">'+
    	'<b>Liker Options:</b> '+
    	'</div>'
    );
}

if (window.location.hostname === "tbooklist.org") {
    // in feed
    if (window.location.pathname.split("/")[1]==="feed"){
        ffn$("div.content-block > div.regular").each(function() {
            var story = new Story({
                namespace: app.namespace,
                instance: this
            });
            app.collection.push(story);
        });
    }
    // book page
    if (window.location.pathname.split("/")[1]==="books"){
        ffn$("div.cmedia-divided__child__top").each(function() {
            var story = new Story({
                namespace: app.namespace,
                instance: this
            });
            app.collection.push(story);
        });
    }

    // hide/show options
    ffn$('div.content-block').after(
    	'<div class="liker_script_options" style="padding:5px; border:1px solid #333399; margin-bottom:5px; background:#D8D8FF;">'+
    	'<b>Liker Options:</b> '+
    	'</div>'
    );
}

//	OPTIONS
//	-  show/hide global options
//

if(app.options("hide_likes")){
	ffn$('.liker_script_options').append('<a href="" class="show_likes" style="color:blue">Show Likes</a>')
	ffn$('.liker_script_options .show_likes').click(function(){ show_likes();  }); 
} else {
	ffn$('.liker_script_options').append('<a href="" class="hide_likes" style="color:blue">Hide Likes</a>')
	ffn$('.liker_script_options .hide_likes').click(function(){ hide_likes(); }); 
}
ffn$('.liker_script_options').append('| ');

if(app.options("hide_dislikes")){
	ffn$('.liker_script_options').append('<a href="" class="show_dislikes" style="color:blue">Show Dislikes</a>')
	ffn$('.liker_script_options .show_dislikes').click(function(){ show_dislikes();  }); 
} else {
	ffn$('.liker_script_options').append('<a href="" class="hide_dislikes" style="color:blue">Hide Dislikes</a>')
	ffn$('.liker_script_options .hide_dislikes').click(function(){ hide_dislikes(); }); 
}
ffn$('.liker_script_options').append('| ');

if(app.options("hide_marked")){
	ffn$('.liker_script_options').append('<a href="" class="show_marked" style="color:blue">Show Marked</a>')
	ffn$('.liker_script_options .show_marked').click(function(){ show_marked();  }); 
} else {
	ffn$('.liker_script_options').append('<a href="" class="hide_marked" style="color:blue">Hide Marked</a>')
	ffn$('.liker_script_options .hide_marked').click(function(){ hide_marked(); }); 
}
ffn$('.liker_script_options').append('| ');

if(app.options("hide_calibre")){
	ffn$('.liker_script_options').append('<a href="" class="show_calibre" style="color:blue">Show Calibre</a>')
	ffn$('.liker_script_options .show_calibre').click(function(){ show_calibre();  }); 
} else {
	ffn$('.liker_script_options').append('<a href="" class="hide_calibre" style="color:blue">Hide Calibre</a>')
	ffn$('.liker_script_options .hide_calibre').click(function(){ hide_calibre(); }); 
}

// test dislike all
if (window.location.hostname === "www.fanfiction.net") {
    ffn$('.liker_script_options').append('| ');
    ffn$('.liker_script_options').append('<a href="" class="dislike_all" style="color:blue">Dislike All Authors</a>')
	ffn$('.liker_script_options .dislike_all').click(function(){ dislike_all();return(false);}); 
}
//


ffn$('.liker_script_options').append('| ');


	ffn$('.liker_script_options').append('<a href="" class="backupToggle" style="color:blue">Manage Site Data</a>');
	ffn$('.liker_script_options').after("<div class='backup_text' style='display:none'>\
		<table><tr>\
		<td class='backup_data' valign='top'>\
			<b>Backup data</b><br />\
			Copy this text some where safe<br />\
			<textarea class=''></textarea>\
		</td>\
		<td>&nbsp;&nbsp;</td>\
		<td class='save_new_data' valign='top'>\
			<b>Upload new Data</b><br>\
			Upload data you had previously saved<br />\
			<textarea></textarea><br >\
			<button class='new_data_save'>save</button>\
		</td></tr></table>\
		</div>");
	ffn$('.backup_text .backup_data textarea').on("click",function(){
		ffn$(this).select();
	});
	ffn$('.backup_text .save_new_data button').on("click",function(){
		var v = ffn$('.backup_text .save_new_data textarea').val();
		try {
			var new_db = JSON.parse(v);
		} catch(err) {
			alert("that data is not valid");
			return;
		}
		localStorage.setItem("FFLikerAA", JSON.stringify(new_db));
		document.location = document.location;
	});
	ffn$('.liker_script_options .backupToggle').click(function(){ 
		ffn$(".backup_text").toggle();
		ffn$(".backup_text .backup_data textarea").html(JSON.stringify(db));
		return false;
	}); 



function show_dislikes(){
	app.options("hide_dislikes",false)
	return false;
}

function hide_dislikes(){
	app.options("hide_dislikes",true)
	return false;
}

function show_likes(){
	app.options("hide_likes",false)
	return false;
}

function hide_likes(){
	app.options("hide_likes",true)
	return false;
}

function show_marked(){
	app.options("hide_marked",false)
	return false;
}

function hide_marked(){
	app.options("hide_marked",true)
	return false;
}

function show_calibre(){
	app.options("hide_calibre",false)
	return false;
}

function hide_calibre(){
	app.options("hide_calibre",true)
	return false;
}

function dislike_all(){
        ffn$("div.z-list:visible").each(function() {
//            console.log(this);
           var story = new Story({
               namespace: app.namespace,
               instance: this
           });

            app.collection.push(story);
            app.author.dislike(story.authorId())
        });
}