// ==UserScript== // @name FanFictionNavigator // @name:ru FanFictionNavigator // @namespace window // @description:en Mark and hide fanfics or authors // @description:ru Выделяет цветом/скрывает фанфики или авторов // @include https://ficbook.net/* // @include https://www.fanfiction.net/* // @include https://archiveofourown.org/* // @include http://archiveofourown.org/* // @include https://tbooklist.org/* // @run-at document-end // @require https://code.jquery.com/jquery-1.7.2.min.js // @require https://greasyfork.org/scripts/17419-underscore-js-1-8-3/code/Underscorejs%20183.js?version=109803 // @version 39 // @grant GM_addStyle // @description Mark and hide fanfics or authors // @downloadURL none // ==/UserScript== // Based on https://chrome.google.com/webstore/detail/fanfiction-organizer/adlnghnicfngjnofbljedmclmdoepcbe // by Stefan Hayden // Fics: const FIC_LIKED = 0; const FIC_DISLIKED = 1; const FIC_MARKED = 2; const FIC_INLIBRARY = 3; // Authors: const AUTHOR_LIKED = 0; const AUTHOR_DISLIKED = 1; // colors. now used for like/dislike/etc links const COLOR_LIKED = '#C4FFCA'; const COLOR_DISLIKED = '#FCB0B0'; const COLOR_MARKED = '#CCCCCC'; const COLOR_INLIBRARY = '#F1D173'; const COLOR_CLEARED = '#FFF'; const COLOR_FB_CLEAR = '#FFF'; // styles for author/story links; links should have only one of these so order doesn't matter GM_addStyle("a.ffn_dislike_fic {text-decoration: line-through; font-weight: bold;}"); GM_addStyle("a.ffn_like_fic {font-weight: bold;} "); GM_addStyle("a.ffn_dislike_author {text-decoration: line-through; font-weight: bold;}"); GM_addStyle("a.ffn_like_author {font-weight: bold;} "); GM_addStyle("a.ffn_mark {font-weight: bold;}"); GM_addStyle("a.ffn_inlibrary {font-weight: bold;}"); // styles for box background; fic style should overwrite author style GM_addStyle(".ffn_like_author:not(a) {background-color:#C4FFCA !important;}"); GM_addStyle(".ffn_dislike_author:not(a) {background-color:#FCB0B0 !important;}"); GM_addStyle(".ffn_like_fic:not(a) {background-color:#C4FFCA !important;}"); GM_addStyle(".ffn_dislike_fic:not(a) {background-color:#FCB0B0 !important;}"); GM_addStyle(".ffn_mark:not(a) {background-color:#CCCCCC !important;}"); GM_addStyle(".ffn_inlibrary:not(a) {background-color:#F1D173 !important;}"); // styles for boxes, they differ between sites /* switch(window.location.hostname){ case "www.fanfiction.net": case "tbooklist.org": GM_addStyle("div.ffn_dislike {background-color:#FCB0B0 !important;}"); GM_addStyle("div.ffn_like {background-color:#C4FFCA !important;}"); GM_addStyle("div.ffn_mark {background-color:#CCCCCC !important;}"); GM_addStyle("div.ffn_inlibrary {background-color:#F1D173 !important;}"); break case "archiveofourown.org": GM_addStyle(".ffn_dislike {background-color:#FCB0B0 !important;}"); GM_addStyle(".ffn_like {background-color:#C4FFCA !important;}"); GM_addStyle(".ffn_mark {background-color:#CCCCCC !important;}"); GM_addStyle(".ffn_inlibrary {background-color:#F1D173 !important;}"); break case "ficbook.net": GM_addStyle("div.ffn_dislike {background-color:#FCB0B0 !important;}"); GM_addStyle("div.ffn_like {background-color:#C4FFCA !important;}"); GM_addStyle("div.ffn_mark {background-color:#CCCCCC !important;}"); GM_addStyle("div.ffn_inlibrary {background-color:#F1D173 !important;}"); GM_addStyle("ul.ffn_dislike {background-color:#FCB0B0 !important;}"); GM_addStyle("ul.ffn_like {background-color:#C4FFCA !important;}"); GM_addStyle("ul.ffn_mark {background-color:#CCCCCC !important;}"); GM_addStyle("ul.ffn_inlibrary {background-color:#F1D173 !important;}"); break } */ // 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(optionsin) { var a = {}; var options = optionsin || {}; 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.inlibrary = function(id) { a.save("fic",id,FIC_INLIBRARY); var story = _.find(a.collection,function(story){ return story.ficId() == id; }); story.fic = FIC_INLIBRARY; story.inlibrary_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(optionsin) { var a = {}; var options = optionsin || {}; 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 = '
'+ 'Story: Like | '+ 'Dislike | '+ 'Mark | '+ 'InLibrary | '+ 'Clear'+ ' Author: Like | '+ 'Dislike | '+ 'Clear'+ '
'; 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 .inlibrary_story').click(function(){ app.fic.inlibrary(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') _this.addClass("ffn_like_fic"); this.$fic.addClass("ffn_like_fic"); break; case FIC_DISLIKED: _this.addClass("ffn_dislike_fic"); this.$fic.addClass("ffn_dislike_fic"); break; case FIC_MARKED: _this.addClass("ffn_mark"); this.$fic.addClass("ffn_mark"); break; case FIC_INLIBRARY: _this.addClass("ffn_inlibrary"); this.$fic.addClass("ffn_inlibrary"); break; } }, set_author: function() { if(this.author === AUTHOR_LIKED) { this.$author.addClass("ffn_like_author"); _this.addClass("ffn_like_author"); } if(this.author === AUTHOR_DISLIKED) { this.$author.addClass("ffn_dislike_author"); _this.addClass("ffn_dislike_author"); } }, like_story: function(){ this.clear_story(); _this.addClass("ffn_like_fic"); this.$fic.addClass("ffn_like_fic"); }, dislike_story: function(){ this.clear_story(); _this.addClass("ffn_dislike_fic"); this.$fic.addClass("ffn_dislike_fic"); }, mark_story: function(){ this.clear_story(); _this.addClass("ffn_mark"); this.$fic.addClass("ffn_mark"); }, inlibrary_story: function(){ this.clear_story(); _this.addClass("ffn_inlibrary"); this.$fic.addClass("ffn_inlibrary"); }, clear_story: function(){ _this.removeClass("ffn_like_fic ffn_dislike_fic ffn_mark ffn_inlibrary"); this.$fic.removeClass("ffn_like_fic ffn_dislike_fic ffn_mark ffn_inlibrary"); }, like_author: function(){ this.clear_author(); this.$author.addClass("ffn_like_author"); _this.addClass("ffn_like_author"); }, dislike_author: function(){ this.clear_author(); this.$author.addClass("ffn_dislike_author"); _this.addClass("ffn_dislike_author"); }, clear_author: function(){ _this.removeClass("ffn_like_author ffn_dislike_author"); this.$author.removeClass("ffn_like_author ffn_dislike_author"); } }; // Specific sites overrides a["www.fanfiction.net"] = { $author: _this.find('a[href^="/u"]:first'), $fic: _this.find('a[href^="/s"]:first'), authorId: function() { if (typeof this.$author.attr('href') === "undefined") { 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() { // do not hide story header on reading page and story block on author page if (! window.location.pathname.split("/")[1].match("^s$|^u$")) _this.hide(); } }; // a["archiveofourown.org"] = { $author: _this.find('a[href^="/users/"]:first'), $fic: _this.find('a[href^="/works/"]:first'), authorId: function() { // old: return this.$author.attr('href').split('/')[2]; // Contributed by Vannis: if (this.$author.length === 0) { return 0; } 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("/")[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].replace(/(\d+).*?$/,"$1"); } else { return this.$fic.attr('href').split('/')[2].replace(/(\d+).*?$/,"$1"); } }, hide:function(){ if (window.location.pathname.split("/")[1]!=="readfic" && window.location.pathname.split("/")[2]!=="favourites") { _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').trim().split('/')[4]; } }, ficId: function() { if (window.location.pathname.split("/")[1] === "books") { return window.location.pathname.trim().split("/")[2]; } if (this.$fic.length === 0) { return 0; } else { return this.$fic.attr('href').trim().split('/')[4]; } }, 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_inlibrary") === true && b.fic === FIC_INLIBRARY)){ // if(b.fic !== true && b.author) { // for liked fics of disliked authors b.hide(); // } } return b; }; var app = new Application({namespace:document.location.host, db: db}); // Adding action links and navigation shortcuts to pages switch(window.location.hostname){ case "www.fanfiction.net": // adding hotkeys // added toggle option, suggested by Vannius if (app.options("enable_list_hotkeys")) { document.addEventListener('keydown', function(e){ switch (e.keyCode){ case 37: var Prev = ffn$("a:contains('« Prev')"); if (typeof(Prev[0])!=='undefined') {Prev[0].click();} break; case 39: var Next = ffn$("a:contains('Next »')"); if (typeof(Next[0])!=='undefined') {Next[0].click();} break; } }, false); } if (app.options("enable_read_hotkeys")) { document.addEventListener('keydown', function(e){ switch (e.keyCode){ case 37: var Prev = ffn$("button:contains('< Prev')"); if (typeof(Prev[0])!=='undefined') {Prev.click();} break; case 39: var Next = ffn$("button:contains('Next >')"); if (typeof(Next[0])!=='undefined') {Next.click();} break; } }, false); } // links in list ffn$(".z-list").each(function(){ 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( '
'+ 'Liker Options: '+ '
' ); break; case "archiveofourown.org": // adding hotkeys if (app.options("enable_list_hotkeys")) { document.addEventListener('keydown', function(e){ switch (e.keyCode){ case 37: var Prev = ffn$("a:contains('← Previous')"); if (typeof(Prev[0])!=='undefined') {Prev[0].click();} break; case 39: var Next = ffn$("a:contains('Next →')"); if (typeof(Next[0])!=='undefined') {Next[0].click();} break; } }, false); } if (app.options("enable_read_hotkeys")) { document.addEventListener('keydown', function(e){ switch (e.keyCode){ case 37: var Prev = ffn$("a:contains('←Previous Chapter')"); if (typeof(Prev[0])!=='undefined') {Prev[0].click();} break; case 39: var Next = ffn$("a:contains('Next Chapter →')"); if (typeof(Next[0])!=='undefined') {Next[0].click();} break; } }, false); } // in lists // old: ffn$("ol.work.index.group > li").each(function(){ // contribution by Vannius from greasyfork site ffn$(".blurb").each(function(){ var story = new Story({ namespace: app.namespace, instance: this }); app.collection.push(story); }); // on reading page ffn$("div.preface.group").each(function(){ var story = new Story({ namespace: app.namespace, instance: this }); app.collection.push(story); }); // hide/show options ffn$('div.navigation.actions.module').after( '
'+ 'Liker Options: '+ '
' ); break; case "ficbook.net": // on reading page patharr = window.location.pathname.split("/"); if (patharr[1]==="readfic"){ ffn$("div.row.hat-row > ul.list-unstyled").each(function() { var story = new Story({ namespace: app.namespace, instance: this }); app.collection.push(story); }); if (app.options("enable_read_hotkeys")) { document.addEventListener('keydown', function(e){ var textcontent; switch (e.keyCode){ case 37: var Prev = ffn$("a.btn-back"); if (Prev.length>0) window.location.href = Prev[0]; break; case 39: var Next = ffn$("a.btn-next"); if (Next.length>0) window.location.href = Next[0]; break; case 38: textcontent = document.getElementById("content"); textcontent.outerHTML = textcontent.outerHTML.replace(/
\n( )*
/gi,"
"); break; case 40: textcontent = document.getElementById("content"); textcontent.outerHTML = textcontent.outerHTML.replace(/
/gi,"
\n
"); break; } }, false); } } // in lists if (patharr[1]==="find" || //(patharr[1]==="popular") || (patharr[1]==="collections") || (patharr[1]==="fanfiction") || (patharr[3]==="profile" && patharr[4]==="works") || // in author profile / works (patharr[1] === "home" && ["favourites","collections"].indexOf(patharr[2])!=-1) ){ // indexOf => checks if patharr[2] is in [] array //ffn$(".description").each(function() { ffn$("article.block > div.description").each(function() { var story = new Story({ namespace: app.namespace, instance: this }); app.collection.push(story); }); } // button for quickly reading/unreading story if (patharr[1]==="find" || (patharr[1]==="popular") || (patharr[1]==="authors" && patharr[3]==="profile" && patharr[4]==="works")) { ffn$("article.block > div.description").each(function() { _this = ffn$(this); ficId = _this.find('a[href^="/readfic"]:first').attr('href').split('/')[2].replace(/(\d+).*?$/,"$1"); if (_this.find(".read-notification").length===0) { _this.append(''); } else { _this.append(''); } }); } // add hotkeys if (app.options("enable_list_hotkeys")) { document.addEventListener('keydown', function(e){ switch (e.keyCode){ case 37: var Prev = ffn$("a[aria-label='Предыдущая']"); if (Prev.length>0) Prev[0].click(); break; case 39: var Next = ffn$("a[aria-label='Следующая']"); if (Next.length>0) Next[0].click(); break; } }, false); } // hide/show options ffn$('section.content-section').after( '
'+ 'Liker Options: '+ '
' ); break; case "tbooklist.org": var patharr = window.location.pathname.split("/"); // in feed if (patharr[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 else if (patharr[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( '
'+ 'Liker Options: '+ '
' ); break; } // OPTIONS // - show/hide global options // if(app.options("hide_likes")){ ffn$('.liker_script_options').append('Show Likes'); ffn$('.liker_script_options .show_likes').click(function(){ show_likes(); }); } else { ffn$('.liker_script_options').append('Hide Likes'); 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('Show Dislikes'); ffn$('.liker_script_options .show_dislikes').click(function(){ show_dislikes(); }); } else { ffn$('.liker_script_options').append('Hide Dislikes'); 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('Show Marked'); ffn$('.liker_script_options .show_marked').click(function(){ show_marked(); }); } else { ffn$('.liker_script_options').append('Hide Marked'); ffn$('.liker_script_options .hide_marked').click(function(){ hide_marked(); }); } ffn$('.liker_script_options').append('| '); if(app.options("hide_inlibrary")){ ffn$('.liker_script_options').append('Show InLibrary'); ffn$('.liker_script_options .show_inlibrary').click(function(){ show_inlibrary(); }); } else { ffn$('.liker_script_options').append('Hide InLibrary'); ffn$('.liker_script_options .hide_inlibrary').click(function(){ hide_inlibrary(); }); } // dislike all authors, currently on ffnet only (enter some slash community and blacklist everyone there, saves time when browsing HP fanfics later) if (window.location.hostname === "www.fanfiction.net") { ffn$('.liker_script_options').append('| '); ffn$('.liker_script_options').append('Dislike All Authors'); ffn$('.liker_script_options .dislike_all').click(function(){ dislike_all();return(false);}); } ffn$('.liker_script_options').append('| FFN Options'); ffn$('.liker_script_options').after( "" ); ffn$('#ffn_import_file_button').click(function(){ var selectedFile = document.getElementById('ffn_import_file_box').files.item(0); if (selectedFile === null) return; fileToText(selectedFile, (text) => { var new_db; try { new_db = JSON.parse(text); } catch(err) { alert("JSON data in file is invalid"); return; } localStorage.setItem("FFLikerAA", JSON.stringify(new_db)); document.location = document.location; }); }); function fileToText(file, callback) { const reader = new FileReader(); reader.readAsText(file); reader.onload = () => { callback(reader.result); }; } ffn$('#ffn_OptionsToggle').click(function(){ ffn$("#ffn_options_block").toggle(); ffn$("#ffn_checkbox_hide_likes").prop("checked",app.options("hide_likes")); ffn$("#ffn_checkbox_hide_dislikes").prop("checked",app.options("hide_dislikes")); ffn$("#ffn_checkbox_hide_marked").prop("checked",app.options("hide_marked")); ffn$("#ffn_checkbox_hide_inlibrary").prop("checked",app.options("hide_inlibrary")); ffn$("#ffn_checkbox_enable_list_hotkeys").prop("checked",app.options("enable_list_hotkeys")); ffn$("#ffn_checkbox_enable_read_hotkeys").prop("checked",app.options("enable_read_hotkeys")); return false; }); ffn$('#ffn_options_button_save').click(function(){ app.options("hide_likes", ffn$("#ffn_checkbox_hide_likes").prop("checked")); app.options("hide_dislikes", ffn$("#ffn_checkbox_hide_dislikes").prop("checked")); app.options("hide_marked", ffn$("#ffn_checkbox_hide_marked").prop("checked")); app.options("hide_inlibrary", ffn$("#ffn_checkbox_hide_inlibrary").prop("checked")); app.options("enable_list_hotkeys", ffn$("#ffn_checkbox_enable_list_hotkeys").prop("checked")); app.options("enable_read_hotkeys", ffn$("#ffn_checkbox_enable_read_hotkeys").prop("checked")); location.reload(); return false; }); // import/export db data /* old import/export, with textboxes 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(); var new_db; try { 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$('.backupToggle').click(function(){ ffn$(".backup_text").toggle(); ffn$(".backup_text .backup_data textarea").html(JSON.stringify(db)); return false; }); //ffn$('.liker_script_options').append('| test' + ''); ffn$('#ffn_export_to_file').click(function(){ var curdate = new Date(); var year = curdate.getFullYear(); var month = curdate.getMonth() + 1; month = month<10? "0"+month : month; var day = curdate.getDate(); day = day<10? "0"+day : day; export_file(JSON.stringify(db,null," "),"FFN_" + window.location.host + "_" + year + "-" + month + "-" + day + ".txt", "text/plain"); return false; }); function export_file(content, fileName, mime) { const blob = new Blob([content], { tipe: mime }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = fileName; a.click(); } 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_inlibrary(){ app.options("hide_inlibrary",false); return false; } function hide_inlibrary(){ app.options("hide_inlibrary",true); return false; } function dislike_all(){ this.ffn$("div.z-list:visible").each(function() { var story = new Story({ namespace: app.namespace, instance: this }); app.collection.push(story); app.author.dislike(story.authorId()); }); }