Novel Ranking Filter [No GM_API Version]

Novel Ranking Filtering Bookmarklet for Mobile Browser

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name           Novel Ranking Filter [No GM_API Version]
// @name:ja        小説ランキングフィルター [GM_APIなし]
// @namespace      https://greasyfork.org/en/users/1264733
// @version        2024-06-23
// @description    Novel Ranking Filtering Bookmarklet for Mobile Browser
// @description:ja モバイルブラウザ用小説ランキングフィルタリングブックマークレット
// @author         LE37
// @license        MIT
// @include        https://www.alphapolis.co.jp/novel/index*
// @include        https://www.alphapolis.co.jp/novel/ranking/*
// @include        https://kakuyomu.jp/genr*
// @include        https://kakuyomu.jp/pick*
// @include        https://kakuyomu.jp/rank*
// @include        https://kakuyomu.jp/sear*
// @include        https://kakuyomu.jp/rece*
// @include        https://syosetu.org/?mode=rank*
// @include        https://yomou.syosetu.com/rank/*
// @include        https://yomou.syosetu.com/search*
// @exclude        https://www.alphapolis.co.jp/novel/ranking/annual
// @exclude        https://yomou.syosetu.com/rank/top/
// @grant          none
// ==/UserScript==

(()=>{
	/*LS20240623*/
	'use strict';
	// GM key, Nodelist, userLink, userid, tag, alt;
	let gMk,eNo,eUl,sId,sTg,eAt;
	// View mode 
	let V=false;
	// Current list
	let O,A,T;
	// Client type
	const M=navigator.userAgent.includes("Mobile");
	const P=location.pathname;
	switch(location.host){
		case "www.alphapolis.co.jp":
			gMk="A";
			eNo="div.section";
			eUl="div.author>a";
			sId=/detail\/(\d+)$/;
			sTg="li.tag a";
			break;
		case "syosetu.org":
			gMk="H";
			eNo=M?"div.search_box":"div.section3";
			eUl=null;
			sId=/:(.*)/;
			sTg=M?'span[id^="tag_"]':'div.all_keyword:nth-child(9) a';
			eAt=M?"p:nth-child(2)":"div.blo_title_sak";
			break;
		case "kakuyomu.jp":
			gMk="K";
			sId=/users\/(.*)$/;
			if(P.startsWith("/search")){
				eNo=M?'div[class*="Spacer_margin-ml-m__"]':'div[class*="NewBox_borderSize-bb"]';
				eUl=M?'span[class*="workLabelAuthor__"] a':"div.partialGiftWidgetActivityName>a";
				sTg='a[href^="/tags/"]';
			}else if(P.startsWith("/recent_r")){
				eNo="div.recentReviews-item";
				eUl="a.widget-workCard-authorLabel";
				sTg='a[href^="/tags/"]';
			}else{
				eNo="div.widget-work";
				eUl="a.widget-workCard-authorLabel";
				sTg="a[itemprop='keywords']";
			}
			break;
		case "yomou.syosetu.com":
			gMk="N";
			if(P.startsWith("/search")){
				eNo=M?"div.smpnovel_list":"div.searchkekka_box";
				eUl=M?null:"a:nth-child(2)";
				sId=M?/:(.*)/:/\/(\d+)/;
				sTg='a[href*="?word"]';
				eAt="p.author";
			}else{
				eNo="div.p-ranklist-item";
				eUl="div.p-ranklist-item__author a";
				sId=/\/(\d+)/;
				sTg="div.p-ranklist-item__keyword a";
			}
			break;
	}
	//console.log( {gMk, eNo, eUl, sId, sTg, eAt} );
	// Read list
	function URD(){
		const G=JSON.parse(localStorage.getItem(gMk));
		O=G?G:{AL:[],TL:[]};
		A=O.AL;
		T=O.TL;
	}
	// Save list
	function USV(){
		if(JSON.stringify(O)!==localStorage.getItem(gMk)){
			localStorage.setItem(gMk,JSON.stringify(O));
		}
	}
	// Run
	URD();
	FMD();
	CFB();
	// Filtering multiple targets
	function FMD(){
		const no=document.querySelectorAll(eNo);
		for(let i=0;i<no.length;i++){
			let rBk=false;
			let uId;
			// Filtering content contain single id(link) or text
			let eLk=eUl?no[i].querySelector(eUl):no[i].querySelector(eAt);
			if(eLk!==null||(gMk==="N"&&M)){
				if(!eLk){
					// Narou search mobile no author link
					if(gMk==="N"){
						const tca=document.createElement("p");
						tca.classList.add("author");
						tca.style.color="#fe7643";
						const head=no[i].querySelector("div.accordion_head");
						// AD
						if(!head){
							//console.log("===A D===");
							//rBk = true;
							continue;
						}
						tca.textContent=head.textContent.split("\n")[3];
						no[i].querySelector("a.read_button").after(tca);
						eLk=tca;
						uId=eLk.textContent.match(sId)[1];
					}
				}else{
					uId=eUl?eLk.href.match(sId)[1]:eLk.textContent.match(sId)[1];
				}
				//console.log(uId);
				rBk=CHK(eLk,"a",A,uId);
			}
			if(sTg&&!rBk){
				// Filtering content contain multiple tags(text)
				// Tag node
				let tno;
				// Hameln mobile origin tag, custom tag
				let tot,tct;
				if(gMk==="H"&&M){
					tot=no[i].querySelector(".trigger p:nth-child(4)");
					tct=no[i].querySelector(sTg);
					if(!tct){
						tno=tot.textContent.slice(3).match(/[^\s]+/g);
						tot.innerHTML="";
					}else{
						tno=no[i].querySelectorAll(sTg);
					}
				}else{
					tno=no[i].querySelectorAll(sTg);
				}
				for(let j=0;j<tno.length;j++){
					let tag;
					if(tot&&!tct){
						tag=tno[j];
						tot.innerHTML+='<span id="tag_'+j+'">'+tag+'</span>';
					}else{
						tag=tno[j].textContent;
					}
					//console.log(tag);
					rBk=tot&&!tct?CHK(no[i].querySelector("span#tag_"+j),"t",T,tag):CHK(tno[j],"t",T,tag);
					if(rBk)break;
				}
			}
			// Blocked show type
			no[i].style.display=!V&&rBk?"none":"";
			no[i].style.opacity=V&&rBk?"0.5":"1";
		}
	}
	// Check keyword
	function CHK(e,n,l,s){
		const r=l.some((v)=>s===v);
		if(!e.classList.contains("c_h_k")){
			e.classList.add("c_h_k");
			e.setAttribute("data-r",n+s);
		}
		if(V){
			e.style.border=r?"thin solid fuchsia":"thin solid dodgerblue";
		}else{
			e.style.border="none";
		}
		return r;
	}

	// Select mode
	function SVM(){
		const bt=document.getElementById("r_fcb");
		if(!V){
			V=true;
			bt.textContent="📙";
			document.addEventListener("click",ECH);
			URD();
		}else{
			V=false;
			bt.textContent="📘";
			document.removeEventListener("click",ECH);
			// Auto save list
			USV();
		}
		FMD();
	}
	// Handler
	function ECH(e){
		e.preventDefault();
		const eT=e.target;
		const tE=eT.classList.contains("c_h_k")?eT
					:eT.parentElement.classList.contains("c_h_k")?eT.parentElement
					:null;
		//console.log(tE);
		if(tE){
			const tda=tE.getAttribute("data-r");
			const tlst=tda.slice(0,1)==="a"?A:T;
			const tid=tda.slice(1);
			const li=tlst.findIndex((v)=>v===tid);
			if(li!==-1){
				tlst.splice(li,1);
			}else{
				tlst.push(tid);
			}
			FMD();
		}
	}

	// Update Blocklists List
	function UBL(){
		alert(gMk+":"+localStorage.getItem(gMk));
	}
	// Sort Blocklists List
	function SBL(){
		A.sort();
		T.sort();
		USV();
		UBL();
	}
	// Delete Block List
	function DBL(){
		const t=prompt("Delete?","No");
		if(t==="Yes"){
			localStorage.removeItem(gMk);
			URD();
			UBL();
			FMD();
		}
	}
	// Create Float Button
	function CFB(){
		BCR("r_fcb","📘","2","2");
		BCR("r_ubl","♻","4","2");
		BCR("r_dbl","📛","4","4");
		BCR("r_sbl","🔀","2","4");
		document.addEventListener("click",BLM);
	}
	function BLM(e){
		switch(e.target.id){
			case "r_fcb":
				SVM();
				break;
			case "r_ubl":
				UBL();
				break;
			case "r_dbl":
				DBL();
				break;
			case "r_sbl":
				SBL();
				break;
		}
	}
	// Button creater
	function BCR(id,text,x,y){
		const cb=document.body.appendChild(document.createElement("button"));
		cb.id=id;
		cb.textContent=text;
		cb.style="position:fixed;width:44px;height:44px;z-index:999;font-size:200%;opacity:50%;cursor:pointer;right:"+x+"em;bottom:"+y+"em;";
		cb.type="button";
	}
})();