(仮)Wizball の詳細ページを保存用に、ちょっといじる Fork

    @@ -175,7 +175,7 @@ if (more_btn) { d_.head.appendChild(Object.assign(d_.createElement("style"), { innerHTML: [ - 'body: {', + 'body {', ' max-width: 640px;', '}', '.wrap.home_end .content .qna_area_inner .comment_area .comment_item_inner .comment_txt {',
    @@ -204,8 +204,11 @@ ' padding-bottom: 10px;', '}', '.qna_area.question .vote_area {', - ' padding: 14px 22px 0;', + ' padding-left: 22px;', '}', + '.vote_area {', + ' padding-top: 14px;', + '}', '.vote_value {', ' padding-bottom: 10px;', '}',
    @@ -215,6 +218,9 @@ '}', '.voter_item {', ' display: inline-block;', + '}', + '.related_question_area {', + ' display: none;', '}', ].join(""), }));
  • /*
     * @title (未完成)Wizball の詳細ページを保存用に、ちょっといじる
     * @description (未完成)Wizball の詳細ページを保存用に、ちょっといじる
     * @include https://m.wizball.io/questions/*
     * @license MIT License http://opensource.org/licenses/MIT
     * @javascript_url *
     */
    /*
    	全ページ読み込む
    
    	create 2019-07-03
    */
    (async _ => {
    	const d_ = document;
    	if (location.hostname != "m.wizball.io") {
    		alert("Please use at m.wizball.io !");
    		return;
    	}
    	async function display_comments() {
    		console.log("!!! load comments !!!");
    		const list = d_.querySelectorAll(".comment_list");
    		for (let i = 0 ; i < list.length ; ++i) {
    			const first_item = list[i].querySelector(".comment_txt");
    			if (! first_item) {		// 質問はコメントがなくても UL 要素がある
    				continue;
    			}
    			const orig_url = first_item.href;
    			const url_base = orig_url.replace(/questions/, "apis/v1/questions");
    			const comments = [];
    			let page = 1;
    			while (true) {
    				const url = url_base + "?page=" + page + "&size=50&sort=LATEST";
    				const resp = await fetch(url);
    				const json = await resp.json();
    				if (json.length > 0) {
    					comments.push(... json);
    					page += 1;
    				} else {
    					break;
    				}
    			}
    			console.log(comments);
    			list[i].innerHTML = "";
    			comments.forEach(c => {
    				let img;
    				if (c.author.image) {
    					img = [
    						'<img src="https://obs.line-scdn.net/',
    						c.author.image.hash,
    						'/s150" class="user_20" title="',
    						c.author.nickname,
    						'">'
    					].join("");
    				} else {
    					img = '<img src="" class="user_20" title="' + c.author.nickname + '">';
    				}
    				const item = Object.assign(d_.createElement("li"), {
    					className: "comment_item",
    					innerHTML: [
    						'<div class="comment_item_inner"><div class="profile_img comment_icon">',
    						img,
    						'</div><a href="/users/',
    						c.author.id,
    						'" class="user_id">',
    						c.author.nickname,
    						'</a> <a href="',
    						orig_url,
    						'" class="comment_txt type_space">',
    						c.text,
    						'</a></div>',
    					].join(""),
    				});
    				list[i].appendChild(item);
    			});
    			const comment_value = list[i].parentNode.querySelector(".comment_list ~ .comment_value");
    			console.log(comment_value);
    			list[i].parentNode.insertBefore(comment_value, list[i]);
    		}
    	}
    
    	async function load_q(qid) {
    		const resp = await fetch("/apis/v1/questions/" + qid);
    		const json = await resp.json();
    		return json;
    	}
    	async function load_a(qid) {
    		const map = {};
    		for (let p = 1 ; p <= 300 ; ++p) {
    			const resp = await fetch("/apis/v1/questions/" + qid + "/answers?page=" + p + "&size=50&sort=POPULAR");
    			const json = await resp.json();
    			if (json.length == 0) {
    				break;
    			}
    			json.forEach(a => {
    				map[a.id] = a;
    			});
    		}
    		return map;
    	}
    	async function load_v(a) {
    		let ub;
    		if (a.questionId) {		// answer
    			ub = "/apis/v1/questions/" + a.questionId + "/answers/" + a.id + "/voters?size=50&sort=LATEST&";
    		} else { // question
    			ub = "/apis/v1/questions/" + a.id + "/votes?size=50&sort=LATEST&";
    		}
    		const list = [];
    		for (let p = 1 ; p <= 300 ; ++p) {
    			const resp = await fetch(ub + "page=" + p);
    			const json = await resp.json();
    			if (json.length == 0) {
    				break;
    			}
    			list.push(... json);
    		}
    		return list;
    	}
    
    	function modify_time(e, q) {
    		const qt = e.querySelector(".user_info_detail.date");
    		qt.innerHTML = (new Date(q.createdAt)).toLocaleString();
    	}
    
    	async function display_voters(e, a) {
    		const eopt = e.querySelector(".qna_option_area");
    		const ea = d_.createElement("div");
    		ea.className = "vote_area";
    		eopt.parentNode.insertBefore(ea, eopt);
    //		eopt.parentNode.insertBefore(eul, eopt);
    		const v = await load_v(a);
    		ea.innerHTML = '<div class="vote_value">Vote : ' + v.length + '</div>';
    		const eul = d_.createElement("ul");
    		ea.appendChild(eul);
    		eul.className = "voter_list";
    		v.forEach(v => {
    			const li = eul.appendChild(d_.createElement("li"));
    			li.className = "voter_item profile_img";
    //			li.innerHTML = v.author.nickname + ", ";
    			if (v.author.image) {
    				li.innerHTML = '<img src="https://obs.line-scdn.net/' + v.author.image.hash + '/s150" class="user_20" title="' + v.author.nickname + '">';
    			} else {
    				li.innerHTML = '<img src="" class="user_20" title="' + v.author.nickname + '">';
    			}
    		});
    	}
    
    	async function modify_data() {
    		const m = /\/questions\/(\d+)/.exec(location.href);
    		const qid = m[1];
    		const q = await load_q(qid);
    		const qe = d_.querySelector(".qna_area.question");
    		modify_time(qe, q);
    //		const qv = await load_v(q);
    		await display_voters(qe, q);
    
    		const a = await load_a(qid);
    		const ae = d_.querySelectorAll(".qna_area.answer .answer_item");
    		console.log(ae);
    		for (let i = 0 ; i < ae.length ; ++i) {
    			const bc = ae[i].querySelector(".btn_comment");
    			const m = /answers\/(\d+)/.exec(bc.href);
    			const aid = m[1];
    			modify_time(ae[i], a[aid]);
    //			const av = await load_v(a);
    			await display_voters(ae[i], a[aid]);
    		}
    	}
    
    	async function modify_window() {
    		await display_comments();
    		await modify_data();
    	}
    
    	const more_btn = d_.querySelector(".qna_area.answer .btn_more_answer");
    	if (more_btn) {
    		d_.head.appendChild(Object.assign(d_.createElement("style"), {
    			innerHTML: [
    'body {',
    '	max-width: 640px;',
    '}',
    '.wrap.home_end .content .qna_area_inner .comment_area .comment_item_inner .comment_txt {',
    '	max-height: none;',
    '}',
    '.comment_item_inner .comment_icon, .voter_list .voter_item {',
    '	width: 20px;',
    '	height: 20px;',
    '	margin-right: 0.5ex;',
    '}',
    '.comment_item_inner .comment_icon {',
    '	float: left;',
    '}',
    '.user_20 {',
    '	border-radius: 50%;',
    '	width: 100%;',
    '}',
    '.wrap.home_end .content .question_logo {',
    '	font-size: inherit;',
    '	color: inherit;',
    '	font-size: 15px;',
    '	color: #959aa5;',
    '}',
    '.wrap.home_end .content .qna_area_inner .comment_area .comment .comment_value {',
    '	padding-top: 0;',
    '	padding-bottom: 10px;',
    '}',
    '.qna_area.question .vote_area {',
    '	padding-left: 22px;',
    '}',
    '.vote_area {',
    '	padding-top: 14px;',
    '}',
    '.vote_value {',
    '	padding-bottom: 10px;',
    '}',
    '.vote_area {',
    '	color: #959aa5;',
    '	font-size: 15px;',
    '}',
    '.voter_item {',
    '	display: inline-block;',
    '}',
    '.related_question_area {',
    '	display: none;',
    '}',
    		].join(""),
    		}));
    		let n = 0;
    		const answer_list = d_.querySelector(".answer_list");
    		// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
    		const MutationObserver = window.MutationObserver || window.WebkitMutationObserver;
    		const observer = new MutationObserver(async function (records) {
    			n += 1;
    			console.log(n);
    			if (more_btn.style.display != "none") {
    				more_btn.click();
    				if (n > 10) {
    					observer.disconnect();
    				}
    			} else {
    				await modify_window();
    			}
    		});
    		observer.observe(answer_list, { childList: true, /* subtree: true */ });
    
    		if (more_btn.style.display != "none") {
    			more_btn.click();
    		} else {
    			await modify_window();
    		}
    	}
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。