您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
q:非表示 w:アンドゥ b:NGワード Shift+Q/Shift+B:NG編集 12:メモを追加 34:自由メモ Shift+!:メモを編集 Shift+":自動メモのみ全削除 .:上限価格
当前为
// ==UserScript== // @name ヤフオクで非表示とメモ // @description q:非表示 w:アンドゥ b:NGワード Shift+Q/Shift+B:NG編集 12:メモを追加 34:自由メモ Shift+!:メモを編集 Shift+":自動メモのみ全削除 .:上限価格 // @match *://auctions.yahoo.co.jp/search/* // @match *://page.auctions.yahoo.co.jp/jp/auction/* // @version 0.3 // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @run-at document-idle // @namespace https://greasyfork.org/users/181558 // ==/UserScript== (function() { const ENABLEAUTOMEMO = 1; const CUSTOMAUTOMEMORE = /(\[\s*関東\s*\]\s*[0-9,0-9,]*\s*円)/m; // 無指定:/$()^/m; (例)掃除機検索用:/(仕事率[^0-90-9\n]*[0-9,0-9,]*\s*[wW])/m; const ENABLEREPORT = 1; // 0で非表示が働いてもレポートを表示しない const COLOR1 = "#6080ff", COLOR2 = "#c03020", COLOR3 = "#808080", KEYHIDE = "q", KEYUNDO = "w", KEYBW = "b", KEYEDIT = "Shift+Q", KEYEDIT2 = "Shift+B", KEYMAXP = ".", KEYMEMO1 = "1", KEYMEMO2 = "2", KEYMEMO1S = "3", KEYMEMO2S = "4", KEYRESETMEMO = "Shift+!", KEYRESETMEMOAUTO = "Shift+\""; var mousex = 0; var mousey = 0; document.addEventListener('keydown', function(e) { if (/input|textarea/i.test(e.target.tagName) == false) { var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key; if (key === KEYHIDE) { // hide e.preventDefault(); var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey); blockElement(ele); } if (key == KEYUNDO) { // undo e.preventDefault(); let undoTitle = (pref('YAJSearchHideTitle') || "").match(/\|[^\|]*$|^[^|]*$/); pref('YAJSearchHideTitle', (pref('YAJSearchHideTitle') || "").replace(/\|[^\|]*$|^[^|]*$/, "")) if (undoTitle[0]) { showByTitle(undoTitle[0].replace(/^\|/, "")) popup2(undoTitle[0].replace(/^\|/, "") + "<br>を非表示登録から削除しました<br><br>編集後:<br>" + (pref('YAJSearchHideTitle') || "").substr(0, 500)); } } if (key == KEYBW) { // NGword e.preventDefault(); addNGWord(); } if (key === KEYEDIT || key === KEYEDIT2) { // edit NGs e.preventDefault(); let tmp = prompt(KEYEDIT + "/" + KEYEDIT2 + ":\n非表示にするタイトルを正規表現で編集してください\n|で区切ると複数指定できます\n\n" + (pref('YAJSearchHideTitle') || ""), pref('YAJSearchHideTitle') || ""); if (tmp !== null) { pref('YAJSearchHideTitle', tmp || "") location.reload(); } } if (key == KEYMEMO1) { // 1memo e.preventDefault(); var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey); memoElement(ele, document); } if (key == KEYMEMO2) { // 2memo e.preventDefault(); var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey); memoElement(ele, document, COLOR2); } if ((key == KEYMEMO1S || key == KEYMEMO2S)) { // free memo e.preventDefault(); var target = (prompt("メモを付けたい出品物のタイトルが含むキーワードを入力してください") || "").trim(); if (!target) return; var memo = (prompt("「" + target + "」\nのメモを書いてください") || "").trim(); if (!memo) return; storeMemo(target.trim(), memo, key == KEYMEMO1S ? COLOR1 : COLOR2) } if (key == KEYRESETMEMO) { // reset e.preventDefault(); console.log(pref('YAJSearchMyMemo')) let tmp = prompt(KEYRESETMEMO + ":\nメモをJSON形式で編集してください\n空欄を入力すれば全削除されます\n\n" + JSON.stringify(pref('YAJSearchMyMemo') || []), JSON.stringify(pref('YAJSearchMyMemo') || [])); if (tmp !== null) { pref('YAJSearchMyMemo', tmp || []); location.reload(); } } if (key == KEYRESETMEMOAUTO) { // reset auto e.preventDefault(); console.log(pref('YAJSearchMyMemo')) var str = pref('YAJSearchMyMemo') || '[]'; var newstr = str.filter(e => !(e.c == COLOR3)); var newstr2 = str.filter(e => (e.c == COLOR3)); if (confirm(KEYRESETMEMOAUTO + ":\n自動メモのみ全て削除します。良いですか?\n\n消すもの:\n" + JSON.stringify(newstr2))) { pref('YAJSearchMyMemo', JSON.stringify(newstr)); popup2("自動メモをクリアしました", 1); location.reload(); } } if (location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") == -1) { if (key == KEYMAXP) { // maxprice e.preventDefault(); let ele = eleget0('//input[@class="InputText__input" and @name="max"]'); if (ele) { ele.focus(); ele.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" }); ele.select(); } popup2("上限価格にフォーカス", 1); } } } }, false); document.addEventListener("mousemove", function(e) { mousex = e.clientX; mousey = e.clientY; }, false); setTimeout(() => { run() }, 100); document.body.addEventListener('AutoPagerize_DOMNodeInserted', function(evt) { run(evt.target); }, false); function run(node = document) { if (pref('YAJSearchMyMemo')) { for (let a of pref('YAJSearchMyMemo')) { memoByTitle(a.t, a.m, node, a.c || COLOR1); } } let help = KEYHIDE + ":非表示 " + KEYUNDO + ":アンドゥ " + KEYBW + ":NGワード " + KEYEDIT + "/" + KEYEDIT2 + ":NG編集 " + KEYMEMO1 + KEYMEMO2 + ":メモを追加 " + KEYMEMO1S + KEYMEMO2S + ":自由メモ " + KEYRESETMEMO + ":メモを編集 " + KEYRESETMEMOAUTO + ":自動メモのみ全削除 " + KEYMAXP + ":上限価格"; if (pref('YAJSearchHideTitle')) { var i = 0; for (let title of pref('YAJSearchHideTitle').split("|")) { i += hideByTitle(title, node); } if (i && ENABLEREPORT) { help = i + "個の出品を非表示にしました<BR>" + help; } } popup2(help, 1) if (ENABLEAUTOMEMO && (location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1)) { autoMemo(CUSTOMAUTOMEMORE, document.body); autoMemo(/(レターパック[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m, document.body); autoMemo(/(クリックポスト[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m, document.body); autoMemo(/(ゆうメール[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m, document.body); autoMemo(/(ゆうパケット[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m, document.body); autoMemo(/(ゆうパック[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m, document.body); autoMemo(/(定形外[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m, document.body); autoMemo(/送料\s*(.*は[0-9,0-9,]*円[-~]?)/m, document.body); // autoMemo(/送料\s*.*一律[^0-90-9\n]*([0-9,0-9,]*円)/m, document.body); autoMemo(/送料\s*(全国一律[0-9,0-9,]*円[-~]?)/m, document.body); //autoMemo(/()/m, document.body); //autoMemo(/()/m, document.body); autoMemo(/([0-90-9]{2,4}年製)/m, eleget0('//h1[@class="ProductTitle__text"]')) ? 0 : autoMemo(/([0-90-9]{2,4}年)/m, eleget0('//h1[@class="ProductTitle__text"]')) ? 0 : autoMemo(/([0-90-9]{2,4}年製)/m, eleget0('//div[@id="adoc"]')) ? 0 : autoMemo(/([0-90-9]{2,4}年)/m, eleget0('//div[@id="adoc"]')); autoMemo(/(ジャンク.*)$/m, eleget0('//h1[@class="ProductTitle__text"]')) ? 0 : autoMemo(/(^.*ジャンク.*)$/m, eleget0('//div[@id="adoc"]')); autoMemo(/発送元:(.{1,4}[都道府県])/m, document.body); } return; } function autoMemo(re, node) { let sou = node.innerText.match(re); if (sou) { var memo = sou[1]; //node.innerHTML=node.innerHTML.replace(re,"<mark>$1</mark>"); var title = getTitle(); var tmp = pref('YAJSearchMyMemo') || []; var isExist = tmp.filter(e => e.t == title && e.m == memo); if (isExist.length == 0) { storeMemo(title, memo, COLOR3, node); } return true; } return false; } function getTitle(x, y) { var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey); if (!ele) return; var title = checkSome(ele); if (!title) return; return title; } function memoElement(ele, node, color = COLOR1) { //A memo if (!ele) return; var title = checkSome(ele); if (!title) return; var memo = (prompt("「" + title + "」\nのメモを書いてください") || "").trim(); storeMemo(title, memo, color, node); return true; } function storeMemo(title, memo, color = COLOR1, node = document) { if (title && memo) { let tmp = pref('YAJSearchMyMemo') || []; tmp.push({ t: title, m: memo, c: color }) pref('YAJSearchMyMemo', tmp) memoByTitle(title, memo, node, color); } } function memoByTitle(title, memo, node, color) { var xp = '//a[contains(@class,"Product__titleLink") and contains(text(),"' + title + '")]/../..|.//h1[@class="ProductTitle__text" and contains(text(),"' + title + '")]/..'; for (var titleEle of elegeta(xp, node)) { if (titleEle) { var ele = titleEle.parentNode.parentNode.insertBefore(document.createElement("span"), titleEle.parentNode.nextSibling); ele.innerHTML = '<span class="' + escape(title + memo + color) + '" title="' + title + '" style="font-size:90%; font-weight:bold; margin:0px 1px; text-decoration:none !important; text-align:center; padding:1px 6px 1px 6px; line-height: 1.4em; border-radius:12px; background-color:' + color + '; color:white;">' + memo + '</span>'; setRemoveMemo(ele, title, memo, color) } } } function setRemoveMemo(ele, title, memo, color) { ele.onclick = (e) => { pref('YAJSearchMyMemo', (pref('YAJSearchMyMemo') || []).filter(n => !(n.t == title && n.m == memo && n.c == color))) for (let e of elegeta('//span[@class="' + escape(title + memo + color) + '"]')) e.remove(); //ele.remove(); } } function checkSome(ele) { if (ele.className == "ProductTitle__text") return ele.innerText.replace(/\|/g, '\|').trim(); for (let i = 0; i < 4; i++) { var ele2 = elegeta('//a[@class="Product__titleLink"]|.//a[@class="Product__titleLink u-textBold"]', ele); if (ele2.length == 1) { return ele2[0].innerText.replace(/\|/g, '\|').trim(); } ele = ele.parentNode; } return; } function blockElement(ele) { //Q toggle if (!ele) return; var title = checkSome(ele); if (!title) return; if ((pref('YAJSearchHideTitle') || "").match(new RegExp("(^|\|)" + title.replace(/(\(|\)|\[|\]|\?|\*|\^|\$|\.|\+|\{|\}|\|)/gm, "\\$1") + "($|\|)"))) { pref('YAJSearchHideTitle', (pref('YAJSearchHideTitle') || "").replace(new RegExp("(^|\|)" + title.replace(/(\(|\)|\[|\]|\?|\*|\^|\$|\.|\+|\{|\}|\|)/gm, "\\$1") + "($|\|)"), "").replace(/(^\|)|(\|\|)|(\|$)/gm, "")); showByTitle(title); popup2(title + "<br>を非表示登録から削除しました<br><br>編集後:<br>" + (pref('YAJSearchHideTitle') || "").substr(0, 500)); return; } else { if ((pref('YAJSearchHideTitle') || "").indexOf(title) != -1) return; } hideByTitle(title); if (pref('YAJSearchHideTitle')) pref('YAJSearchHideTitle', pref('YAJSearchHideTitle') + "|" + title); else pref('YAJSearchHideTitle', title); popup2(title + "<br>を非表示登録しました(" + KEYUNDO + ":取り消し " + KEYEDIT + "/" + KEYEDIT2 + ":編集)<br><br>編集後:<br>" + pref('YAJSearchHideTitle').substr(0, 500)); } function hideByTitle(title, node) { let i = 0; var xp = '//a[contains(@class,"Product__titleLink") and contains(text(),"' + title + '")]/../../../../..'; for (let ele of elegeta(xp, node)) { i++; setTimeout(function() { ele.style.opacity = "0.75" }, 17 * 0); setTimeout(function() { ele.style.opacity = "0.50" }, 17 * 1); setTimeout(function() { ele.style.opacity = "0.25" }, 17 * 2); setTimeout(function() { ele.style.display = "none"; ele.style.opacity = "0" }, 17 * 3); } var xp = '//h1[@class="ProductTitle__text" and contains(text(),"' + title + '")]/../../../..'; for (let ele of elegeta(xp, node)) { i++; ele.style.opacity = "0.5"; } return i; } function showByTitle(title) { var xp = '//a[contains(@class,"Product__titleLink") and contains(text(),"' + title + '")]/../../../../..'; for (let ele of elegeta(xp)) { setTimeout(function() { ele.style.display = "block"; ele.style.opacity = "0.25" }, 17 * 0); setTimeout(function() { ele.style.opacity = "0.50" }, 17 * 1); setTimeout(function() { ele.style.opacity = "0.75" }, 17 * 2); setTimeout(function() { ele.style.opacity = "1" }, 17 * 3); } var xp = '//h1[@class="ProductTitle__text" and contains(text(),"' + title + '")]/../../../..'; for (let ele of elegeta(xp)) { ele.style.opacity = "1"; } } function addNGWord() { var newWord = (prompt("非表示にしたい出品物が含むNGワードを入力してください") || "").trim(); if (newWord) { hideByTitle(newWord) if (pref('YAJSearchHideTitle')) pref('YAJSearchHideTitle', pref('YAJSearchHideTitle') + "|" + newWord); else pref('YAJSearchHideTitle', newWord); popup2(title + "<br>を非表示登録しました(" + KEYUNDO + ":取り消し " + KEYEDIT + "/" + KEYEDIT2 + ":編集)<br><br>編集後:<br>" + pref('YAJSearchHideTitle').substr(0, 500)); } } function elegeta(xpath, node = document) { if (!xpath) return []; try { var array = []; var ele = document.evaluate("." + xpath, node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0; i < ele.snapshotLength; i++) array[i] = ele.snapshotItem(i); return array; } catch (e) { return []; } } function eleget0(xpath, node = document) { if (!xpath) return null; try { var ele = document.evaluate("." + xpath, node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); return ele.snapshotLength > 0 ? ele.snapshotItem(0) : ""; } catch (e) { return null; } } var maet; function popup2(text, i = 0) { var mae = eleget0('//span[@id="mllbox"]'); if (maet && mae) { mae.remove(); clearTimeout(maet); } var ele = document.body.appendChild(document.createElement("span")); ele.outerHTML = '<span id="mllbox" style="all:initial; position: fixed; right:1em; bottom: ' + (i * 2 + 1) + 'em; z-index:2147483647; opacity:1; font-size:90%; margin:0px 1px; text-decoration:none !important; padding:1px 6px 1px 6px; word-break: break-all !important; border-radius:12px; background-color:#6080ff; color:white; ">' + text + '</span>'; maet = setTimeout(function() { var mae = eleget0('//span[@id="mllbox"]'); if (mae) { mae.remove(); } }, 5000); } function pref(name, store = null) { if (store === null) { // 読み出し let data = GM_getValue(name) if (data == undefined) return; // 値がない if (data.substr(0, 1) === "[") { // 配列なのでJSONで返す try { return JSON.parse(data || '[]'); } catch (e) { console.log("データベースがバグってるのでクリアします\n" + e); pref(name, []); return; } } else return data; } if (store === "" || store === []) { // 書き込み、削除 GM_deleteValue(name); return; } else if (typeof store === "string") { // 書き込み、文字列 GM_setValue(name, store); return store; } else { // 書き込み、配列 try { GM_setValue(name, JSON.stringify(store)); } catch (e) { console.log("データベースがバグってるのでクリアします\n" + e); pref(name, ""); } return store; } } })()