// ==UserScript==
// @name ヨドバシ検索結果で量あたり単価を表示
// @description Shift+A/Shift+B:量単価上限で絞り込み A:量単価昇順 .:価格上限入力フォームにフォーカス Shift+Alt+A:価格昇順
// @match *://www.amazon.co.jp/*
// @exclude *://www.amazon.co.jp/*/cart/*
// @exclude *://www.amazon.co.jp/*/buy/*
// @exclude *://www.amazon.co.jp/*/huc/*
// @exclude *://www.amazon.co.jp/*/css/*
// @exclude *://www.amazon.co.jp/ap/*
// @exclude *://www.amazon.co.jp/gp/*
// @exclude *://www.amazon.co.jp/auto-deliveries*
// @match *://jp.iherb.com/*
// @match https://www.kohnan-eshop.com/shop/goods/search.aspx*
// @match https://www.kohnan-eshop.com/shop/e/*
// @match https://www.komeri.com/category/*
// @match https://www.komeri.com/search/*
// @match https://www.komeri.com/disp/*
// @match https://www.komeri.com/topic/*
// @match *://www.yodobashi.com/*
// @match https://order.yodobashi.com/yc/shoppingcart/index.html*
// @match https://order.yodobashi.com/yc/shoppingcart/action.html*
// @match *://kakaku.com/*
// @match *://search.kakaku.com/*
// @grant GM_addStyle
// @version 0.3.2
// @run-at document-idle
// @namespace https://gf.qytechs.cn/users/181558
// @require https://code.jquery.com/jquery-3.6.0.min.js
// ==/UserScript==
this.$ = this.jQuery = jQuery.noConflict(true);
(function() {
const DEBUG = 0; // 1:計算に使った要素をたまに可視化 2:計算に使った要素を常に可視化
const USE_YODOBASHI_METHOD_IN_AMAZON = 0; // 1:Amazonのポイント還元計算でヨドバシと同じ方法を使用 0:ポイントを値引きとして計算
const debug2 = 0; // 1:半透明に消す
var debug = DEBUG;
if (debug == 1) {
debug = Math.random() > (lh("amazon.co.jp") ? 0.1 : 0.8) ? 1 : 0
}
if (typeof $ === "undefined") { window.addEventListener('DOMContentLoaded', function() { run0(); return; }) } else { run0(); }
GM_addStyle(`.ppr,.ppr2 {all:initial;position:relative;z-index:999; display:inline-block; font-weight:bold; font-size:${lh("amazon")?"min(14px,110%)":"min(15px,80%)"}; margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0px 0.5em 0 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap;}`)
function run0() {
if (window != parent) return;
const ddg_google_ratio = 0.2; // 0:100%ddg 1:100%google
const enableBeta = 1; // 1でポイント還元後価格(想像)を表示
var gStaY = 0;
// -----------------------------------------------------
// 上が優先
const SITEINFO = [{
is: 'KOMERI',
urlRE: '//www.komeri.com/category/|https://www.komeri.com/search/|https://www.komeri.com/disp/|https://www.komeri.com/topic/',
titleXPath: '//a[last()]/div[@class="goods-nm"]|//h1/span[@class="goods-nm goods-name-title ttl_font"]',
priceXPath: '//div/div[@class="value prRed"]/span[@class="amt"]|//div[@class="price-area"]/div[@class="price-area-inner sale-pr"]/p[@class="price prRed"]/span[@class="amt"]',
orderPL: 3,
listPL: 3,
isorder: /$^/,
iscate: /$^/,
isproduct: /\/\/www\.komeri\.com\/disp\//,
issearch: /\/search\/|\/category\/|\/topic\//,
sortData: [{ url: /https:\/\/www.komeri.com\/search\//, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: 'li.item' }],
// sortUrl: /https:\/\/www.komeri.com\/search\//,
onLoad: () => {},
onEachItem: (node, titleEle, rndcolor) => {},
pointFunc: (parentEle, price, priceEle, rndcolor) => {},
hide: (title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle) => {
// type1
var pass1 = 0;
title = title.replace(/[A-Za-z0-9]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 0xFEE0) })
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)(mg|㎎|g|ml|mL|枚|粒|錠|包|杯|本|個|袋|ml|組入|ポート|色)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg)/); // /\D([0-9\.]+)\s?(mg|g|ml|mL|mcg)|\D([0-9\.]+)(L|kg)/);
let discreteUnit = /$^/; ///[X×]([0-9\.]+)\s?(.パック|セット|Pack|枚|タブレット|カプセル|個|錠|ベジタリアンカプセル|ベジタブルカプセル|植物性カプセル|Veggie Caps|Veg Capsules|ベジカプセル|べジカプセル|カプセル|粒|ベジキャップ|チュアブル錠|ソフトゼリー|ティーバック|ティーバッグ|袋|Softgels|ソフトジェル|Chewable Tablets|錠|Tablets|グミ|ロゼンジ|植物性液体フィトカプセル|Vegetarian Capsules)/m;
parentEle.style.height = "25em"; // 縦がガタガタになるので大きめで揃える
if (ryou && (ryou[1] > 0 || ryou[3] > 0)) {
if (ryou[4]) ryou[4] = ryou[4].replace(/kg|㎏|Kg/, "g").replace(/L/, "ml"); //.replace(/TB/, "GB");
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
var mul = (title.match(discreteUnit)) ? Number(title.match(discreteUnit)[1]) : 1;
// var ppr = Math.round(100 * (price) / Number(ryout * mul)) / 100;
var ppr = Math.round(1000 * (price) / Number(ryout * mul)) / 1000;
var pprEmbed = (price) / Number(ryout * mul);
titleEle.style.display = "inline";
// var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbed + '" style=" position:relative;z-index:999; display:inline-block; font-weight:bold; font-size:15px;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr + '/' + (ryou[2] || ryou[4]) + (ppr == undefined ? ryou + "," + ryout + "," + mul : "") + '</span>').insertAfter(titleEle);
var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbed + '" >¥' + ppr + '/' + (ryou[2] || ryou[4]) + (ppr == undefined ? ryou + "," + ryout + "," + mul : "") + '</span>').insertAfter(titleEle);
if ((!isproduct) && (!isorder)) setClick(ele, ppr, "\\" + (Math.round(price)) + "/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n");
pass1 = ((iscate || issearch) && cppLimit[1] && ppr <= cppLimit[1] && ryou && ppr) ? 1 : 0;
}
if ((cppLimit[1] > 0 && pass1 == 0) || (cppLimit[1] > 0 && (!ryou1))) debugRemove(parentEle);
// if ((cppLimit[2] > 0 && pass2 == 0) || (cppLimit[2] > 0 && (!ryou))) debugRemove(parentEle);
},
},
// -----------------------------------------------------
{
is: 'KAKAKU',
urlRE: '//kakaku.com/|//search.kakaku.com/',
titleXPath: '//p[contains(@class,"p-item_name s-biggerlinkHover_underline")]|//h2[@itemprop="name"]|.//span[@class="name"]',
priceXPath: '//span[@class="c-num p-item_price_num"]|.//span[@id="minPrice"]/a/span|.//p[@class="p-item_price"]/span|.//span[@class="itemCatPrice"]',
orderPL: 5,
listPL: 5,
isorder: /$^/,
iscate: /$^/,
isproduct: /$^/,
issearch: /search_results|\/\/search\./,
sortData: [
{ sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: 'div.c-list1_cell.p-result_item', },
],
sortUrl: /^https:\/\/kakaku.com\/search_results\/|^https:\/\/search.kakaku.com\//,
onSort: () => {
elegeta('img[data-src][src*="loading.gif"]').forEach((e, i) => {
setTimeout(() => {
e.src = e.dataset.src;
delete e.dataset.src;
}, i * 200)
})
},
onLoad: () => {},
onEachItem: (node, titleEle, rndcolor) => {},
pointFunc: (parentEle, price, priceEle, rndcolor) => {},
hide: (title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle) => {
// type1
var pass1 = 0;
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)(mg|㎎|g|ml|mL|枚|粒|錠|包|杯|本|個|袋|ml|組入|ポート|色)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg)/); // /\D([0-9\.]+)\s?(mg|g|ml|mL|mcg)|\D([0-9\.]+)(L|kg)/);
let discreteUnit = /×([0-9\.]+).*?(セット|Pack|枚|タブレット|カプセル|個|錠|ベジタリアンカプセル|ベジタブルカプセル|植物性カプセル|Veggie Caps|Veg Capsules|ベジカプセル|べジカプセル|カプセル|粒|ベジキャップ|チュアブル錠|ソフトゼリー|ティーバック|ティーバッグ|袋|Softgels|ソフトジェル|Chewable Tablets|錠|Tablets|グミ|ロゼンジ|植物性液体フィトカプセル|Vegetarian Capsules)/m;
if (ryou && (ryou[1] > 0 || ryou[3] > 0)) {
if (ryou[4]) ryou[4] = ryou[4].replace(/kg|㎏|Kg/, "g").replace(/L/, "ml"); //.replace(/TB/, "GB");
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
var mul = (title.match(discreteUnit)) ? Number(title.match(discreteUnit)[1]) : 1;
var ppr = Math.round(100 * (price) / Number(ryout * mul)) / 100;
var pprEmbed = (price) / Number(ryout * mul);
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbed + '" style=" position:relative; z-index:999; display:inline-block; font-weight:bold; font-size:90%;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr + '/' + (ryou[2] || ryou[4]) + (ppr == undefined ? ryou + "," + ryout + "," + mul : "") + '</span>').insertAfter(titleEle);
if ((!isproduct) && (!isorder)) setClick(ele, ppr, "\\" + (Math.round(price)) + "/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n");
pass1 = ((iscate || issearch) && cppLimit[1] && ppr <= cppLimit[1] && ryou && ppr) ? 1 : 0;
}
// type2
var pass2 = 0;
var ryou1 = ryou;
var ryou = title.match(discreteUnit);
if (ryou && (ryou[1] > 0)) {
var ryout = Number(ryou[1]);
var mul = 1;
var ppr2 = Math.round(100 * (price) / Number(ryout * mul)) / 100;
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr2" style=" position:relative; z-index:999; display:inline-block; font-weight:bold; font-size:90%;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr2 + '/' + (ryou[2] || ryou[4]) + '</span>').insertAfter(titleEle);
if ((!isproduct) && (!isorder)) $(ele).css("cursor", "pointer").attr("title", "クリックかShift+Bでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 2, ppr2));
pass2 = ((iscate || issearch) && cppLimit[2] && ppr2 <= cppLimit[2] && ryou && ppr) ? 1 : 0;
}
if (eleget0('//span[contains(@class,"p-switch_btn p-switch_btn-current")]/img[@alt="リスト形式"]')) {
if ((cppLimit[1] > 0 && pass1 == 0) || (cppLimit[1] > 0 && (!ryou1))) debugRemove(parentEle.parentNode);
if ((cppLimit[2] > 0 && pass2 == 0) || (cppLimit[2] > 0 && (!ryou))) debugRemove(parentEle.parentNode);
} else {
if ((cppLimit[1] > 0 && pass1 == 0) || (cppLimit[1] > 0 && (!ryou1))) debugRemove(parentEle.parentNode.parentNode.parentNode.parentNode.parentNode);
if ((cppLimit[2] > 0 && pass2 == 0) || (cppLimit[2] > 0 && (!ryou))) debugRemove(parentEle.parentNode.parentNode.parentNode.parentNode.parentNode);
}
},
},
// -----------------------------------------------------
{
is: 'YODOBASHI',
urlRE: '//.*.yodobashi.com/',
titleXPath: '//div[contains(@class,"pName")]/p[2]|.//h1[@id="products_maintitle"]/span|.//span[@class="js_c_commodityName"]|.//a[@id="LinkProduct01"]|.//div[@class="product js_productName"]|.//a[@class="js_productListPostTag js-clicklog js-taglog-schRlt"]/p[2]',
priceXPath: '//span[@class="productPrice"]|.//span[@id="js_scl_unitPrice"]|.//div[@class="price red"]/strong|.//li[@class="Special"]/em|.//span[@class="red js_ppSalesPrice"]',
pointrateXPath: '//span[@class="spNone"]|.//span[@id="js_scl_pointrate"]|.//div[@class="point orange"]|.//li[@class="Point"]|.//span[@class="orange js_ppPoint"]|.//div[@class="pInfo liMt05"]/ul/li/span[@class="orange ml10"]',
isorder: /https?:\/\/order\./,
issearch: /[\?\&]word\=/,
iscate: /category\//,
isproduct: /\/product\//,
orderPL: 5,
listPL: 3,
sortData: [
{ sortPpr: '//span[@class="ignoreMe ppr2"]', sortElement: '.srcResultItem_block', },
{ sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: '.srcResultItem_block', },
],
sortUrl: /https:\/\/www.yodobashi.com\/category\/|https:\/\/www.yodobashi.com\/.*\?word=|https:\/\/www\.yodobashi\.com\/\?searchbtn=true\&word=|\/\/www\.yodobashi\.com\/.*\&word=/, // todo: |https:\/\/www.yodobashi.com\/maker\/
onLoad: () => { //window.addEventListener('DOMContentLoaded', function(){
// .キーで上限絞り込みにフォーカス、全選択状態
$(document).keypress((e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.getAttribute('contenteditable') === 'true' || ((e.target.closest('#chat-messages,ytd-comments-header-renderer') || document.activeElement.closest('#chat-messages,ytd-comments-header-renderer')))) return;
if (String(e.key) == ".") {
var ele = eleget0('//input[@id="js_upperPrice"]');
e.preventDefault();
if (ele) {
ele.focus();
$(ele).select();
ele.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
}
}
});
$('input#js_upperPrice').css('ime-mode', 'inactive'); // 上限価格はIME offにする
// })
},
onEachItem: (node, titleEle, rndcolor) => {
if (issearch || isproduct) { // 「店頭でのみ販売しています|予定数の販売を終了しました|販売を終了しました」を非表示
for (let ele of elegeta('//div[@class="pInfo"]/ul/li', node)) {
if (ele.innerText.match(/店頭でのみ販売しています|販売を終了しました/)) { debugRemove(ele.parentNode.parentNode.parentNode); continue; }
}
};
for (let site of [
["UserBenchmark", "www.userbenchmark.com", "#609070", /内蔵SSD|内蔵ハードディスク|PCパーツ>CPU|PCパーツ>グラフィックボード|USBメモリ/],
["techpowerup", "www.techpowerup.com Energy Efficiency", "#801010", /PCパーツ>CPU/],
["Backblaze", "www.backblaze.com/blog/hard-drive-stats", "#C51E33", /内蔵SSD|内蔵ハードディスク/],
["kopfhoerer.com", "www.kopfhoerer.com", "#137db0", /用ヘッドセット|型ヘッドホン|Bluetooth対応ヘッドホン|ゲーミングヘッドセット|Bluetoothヘッドセット|イヤホンマイク>3.5mmミニプラグ|インナーイヤーヘッドホン|ヘッドセット・ヘッドホン|ヘッドホン>完全ワイヤレスイヤホン/],
["Kopfhoerer.de", "www.kopfhoerer.de", "#2b2a3a", /型ヘッドホン|Bluetooth対応ヘッドホン|インナーイヤーヘッドホン|ヘッドセット・ヘッドホン|ヘッドホン>完全ワイヤレスイヤホン/],
["RTINGS", "www.rtings.com", "#609070", /用ヘッドセット|型ヘッドホン|Bluetooth対応ヘッドホン|ゲーミングヘッドセット|Bluetoothヘッドセット|イヤホンマイク>3.5mmミニプラグ|インナーイヤーヘッドホン|ヘッドセット・ヘッドホン|ヘッドホン>完全ワイヤレスイヤホン/],
["TFT CENTRAL", "www.tftcentral.co.uk", "#2e2e2e", />ディスプレイ・モニター|ゲーミングモニター/]
]) {
if ((issearch || isproduct || iscate) && ((eleget0('//div[@class="breadcrumbs js_ctlg_ageconfirm_permit"]')?.innerText || "") + " " + ((titleEle.parentNode.parentNode.parentNode.innerText))).match(site[3])) { // RTINGS/kopfhoererリンク
var ele = titleEle.parentNode.parentNode.parentNode.insertBefore(document.createElement("a"), titleEle.parentNode.parentNode.nextSibling);
var iflsite = (Math.random() > ddg_google_ratio) ? "https://duckduckgo.com/?q=!ducky+" : "https://www.google.co.jp/search?btnI=I%27m+Feeling+Lucky&q=";
ele.innerHTML += '<a rel=\"noopener noreferrer nofollow\" href="' + iflsite + (titleEle.innerText.replace(/[\/\?\+\[\]\(\)\u30a0-\u30ff\u3040-\u309f\u3005-\u3006\u30e0-\u9fcf]+/gmi, " ") + ' ').replace(/\s{2,9}/gm, " ") + 'site:' + site[1] + '" style="font-weight:bold; font-size:auto;display:inline-block;margin:1px 1px; padding:0.03em 0.5em 0.03em 0.5em; border-radius:99px; background-color:' + site[2] + '; color:white; white-space: nowrap; ">' + site[0] + '</a>';
}
}
},
pointFunc: (parentEle, price, priceEle, rndcolor) => {
var pointEle = eleget0(SITE.pointrateXPath, parentEle);
if (pointEle) {
var pointtext = pointEle.innerText.replace(/\,/g, "");
if (pointtext.match(/([0-9]+)(?:%)/)) {
debugEle(pointEle, rndcolor);
var pointPer = Number(pointtext.match(/([0-9,]+)(?:%)/)[1] / 100);
} else
if (pointtext.match(/([0-9]+)(?:ポイント)/)) {
debugEle(pointEle, rndcolor);
var pointPer = Number(pointtext.match(/([0-9]+)(?:ポイント)/)[1] / price);
/* if (debug) */
pointEle.innerHTML += "<span style='background-color:#fff8e8;'>(" + Math.round(pointPer * 100) + "%?)</span>";
}
if (pointPer) {
var point = Math.ceil(price - (price * (price / (price + price * pointPer))));
var pricef = Math.round(price - point).toLocaleString();
if (enableBeta) priceEle.innerHTML += " <span style='background-color:#fff0f0;'>" + (isorder ? "<br>還元後:" : "(還元後:") + "¥" + pricef + (isorder ? "" : ")") + "</span>";
}
} else { var point = -1; }
return point;
},
hide: (title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle) => {
// type1
var pass1 = 0;
if (title.match(/ゴミ袋|ポリ袋/) || ((isproduct || issearch) && ((parentEle.innerText)).match(/ゴミ袋|ポリ袋/)))
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)(P)/);
else
if (title.match(/ラップ|クッキングシート/) || ((isproduct || issearch) && ((parentEle.innerText)).match(/ラップ/)))
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)(m)/);
else
if (title.match(/USBメモリ|(外付け|外付|ポータブル|内蔵|バルク|接続)(SSD|HDD|ハードディスク)|バルクドライブ|2\.5.?(inc|インチ)|7mm|9.5mm/) || ((isproduct || issearch) && ((parentEle.innerText)).match(/(内蔵|外付け|ポータブル)(SSD|HDD|ハードディスク)/)))
var ryou = title.replace(/\,/g, "").match(/\s([0-9\.]+)(mg|㎎|g|ml|mL|ml|GB)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg|TB)/i);
else
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)(mg|㎎|g|ml|mL|ml)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg)/i);
if (ryou && (ryou[1] > 0 || ryou[3] > 0)) {
if (ryou[4]) ryou[4] = ryou[4].replace(/kg|㎏|Kg/, "g").replace(/L/, "ml").replace(/TB/, "GB");
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
var mul = (title.match(/×[0-9\.\,]+/m) && !(title.match(/[\((\[].*×.*[\))\]]/m)) && !(title.match(/×[\d\s]*(cm|mm|m)/))) ? Number(title.match(/×([0-9\.\,]+)/)[1]) : 1;
if (point > -1) {
var ppr = Math.round(100 * (price - point) / Number(ryout * mul)) / 100;
var pprEmbed = (price - point) / Number(ryout * mul);
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbed + '" style=" display:inline-block; font-weight:bold; font-size:90%;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr + '/' + (ryou[2] || ryou[4]) + (ppr == undefined ? ryou + "," + ryout + "," + mul : "") + '</span>').insertAfter(titleEle);
if ((!isproduct) && (!isorder)) setClick(ele, ppr, "\\" + (Math.round(price - point)) + "/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n") //$(ele).css("cursor", "pointer").attr("title", "クリックかShift+Aでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 1, ppr));
pass1 = ((iscate || issearch) && cppLimit[1] && ppr <= cppLimit[1]) ? 1 : 0;
}
}
// type2
var pass2 = 0;
var ryou1 = ryou;
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)(冊|袋|枚|粒|錠|包|杯|本|個|袋|組入|ポート|色|日分|ヶ入|食|回分|回用|巻(入|セット|缶|函))/);
if (ryou && (ryou[1] > 0 || ryou[3] > 0)) {
if (ryou[4]) ryou[4] = ryou[4].replace(/kg|㎏|Kg/, "g").replace(/L/, "ml").replace(/TB/, "GB");
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
var mul = 1; //(title.match(/×[0-9\.\,]+/m) && !(title.match(/[\((\[].*×.*[\))\]]/m)) && !(title.match(/×[\d\s]*(cm|mm)/)))?Number(title.match(/×([0-9\.\,]+)/)[1]):1;
if (point > -1) {
var ppr2 = Math.round(100 * (price - point) / Number(ryout * mul)) / 100;
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr2" style=" display:inline-block; font-weight:bold; font-size:90%;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr2 + '/' + (ryou[2] || ryou[4]) + '</span>').insertAfter(titleEle);
if ((!isproduct) && (!isorder)) $(ele).css("cursor", "pointer").attr("title", "クリックかShift+Bでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 2, ppr2));
pass2 = ((iscate || issearch) && cppLimit[2] && ppr2 <= cppLimit[2]) ? 1 : 0;
}
}
if ((cppLimit[1] > 0 && pass1 == 0) || (cppLimit[1] > 0 && (!ryou1))) debugRemove(parentEle);
if ((cppLimit[2] > 0 && pass2 == 0) || (cppLimit[2] > 0 && (!ryou))) debugRemove(parentEle);
},
}, {
// -----------------------------------------------------{
is: 'KOHNAN',
urlRE: '//www.kohnan-eshop.com/shop/goods/search.aspx|//www.kohnan-eshop.com/shop/e/', //|//www.kohnan-eshop.com/shop/g/',
titleXPath: '//div[@class="name1_"]/a[@class="goods_name_"]', //'|//div[@class="mainframe_"]/h1[@class="goods_name_"]',
priceXPath: '//div[3]/span[@class="price_"]', //'|//table[@class="formdetail_ goodsspec_"]/tbody/tr[5]/td/span[@class="price_"]',
orderPL: 3,
listPL: 3,
isorder: /$^/,
iscate: /$^/,
isproduct: /www.kohnan-eshop.com\/shop\/g\//,
issearch: /search/,
sortData: [{ url: /https:\/\/www.kohnan-eshop.com\/shop\/goods\/search.aspx/, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: '.StyleT_Item_', }],
//sortUrl: /https:\/\/www.kohnan-eshop.com\/shop\/goods\/search.aspx/,
onLoad: () => {},
onEachItem: (node, titleEle, rndcolor) => {},
pointFunc: (parentEle, price, priceEle, rndcolor) => {},
hide: (title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle) => {
// type1
var pass1 = 0;
title = title.replace(/[A-Za-z0-9,.]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 0xFEE0) })
var ryou = title.replace(/[A-Za-z0-9,.]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 0xFEE0) }).replace(/\,/g, "").match(/\D([0-9\.]+)(mg|㎎|g|ml|mL|枚|粒|錠|包|杯|本|個|袋|ml|組入|ポート|色)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg)/);
// alert(ryou);
let discreteUnit = /×([0-9\.]+)\s?(セット|Pack|枚|タブレット|カプセル|個|錠|ベジタリアンカプセル|ベジタブルカプセル|植物性カプセル|Veggie Caps|Veg Capsules|ベジカプセル|べジカプセル|カプセル|粒|ベジキャップ|チュアブル錠|ソフトゼリー|ティーバック|ティーバッグ|袋|Softgels|ソフトジェル|Chewable Tablets|錠|Tablets|グミ|ロゼンジ|植物性液体フィトカプセル|Vegetarian Capsules)/m;
if (ryou && (ryou[1] > 0 || ryou[3] > 0)) {
if (ryou[4]) ryou[4] = ryou[4].replace(/kg|㎏|Kg/, "g").replace(/L/, "ml"); //.replace(/TB/, "GB");
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
var mul = (title.match(discreteUnit)) ? Number(title.match(discreteUnit)[1]) : 1;
var ppr = Math.round(100 * (price) / Number(ryout * mul)) / 100;
var pprEmbed = (price) / Number(ryout * mul);
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbed + '" style=" font-size:12px; ">¥' + ppr + '/' + (ryou[2] || ryou[4]) + (ppr == undefined ? ryou + "," + ryout + "," + mul : "") + '</span>').insertAfter(titleEle);
if ((!isproduct) && (!isorder)) setClick(ele, ppr, "\\" + (Math.round(price)) + "/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n");
pass1 = ((iscate || issearch) && cppLimit[1] && ppr <= cppLimit[1] && ryou && ppr) ? 1 : 0;
}
// type2
var pass2 = 0;
var ryou1 = ryou;
var ryou = title.match(discreteUnit);
if (ryou && (ryou[1] > 0)) {
var ryout = Number(ryou[1]);
var mul = 1;
var ppr2 = Math.round(100 * (price) / Number(ryout * mul)) / 100;
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr2" style=" font-size:12px; ">¥' + ppr2 + '/' + (ryou[2] || ryou[4]) + '</span>').insertAfter(titleEle.parentNode);
if ((!isproduct) && (!isorder)) $(ele).css("cursor", "pointer").attr("title", "クリックかShift+Bでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 2, ppr2));
pass2 = ((iscate || issearch) && cppLimit[2] && ppr2 <= cppLimit[2] && ryou && ppr) ? 1 : 0;
}
if ((cppLimit[1] > 0 && pass1 == 0) || (cppLimit[1] > 0 && (!ryou1))) debugRemove(parentEle);
// if ((cppLimit[2] > 0 && pass2 == 0) || (cppLimit[2] > 0 && (!ryou))) debugRemove(parentEle);
},
},
// -----------------------------------------------------
{
is: 'AMAZON', // amazon::
urlRE: 'amazon.co',
priceXPath: '//span/span[1]/span/a[@class="a-button-text" and @id="a-autoid-5-announce"]/span[contains(text(),"¥")]|.//span[@class="a-color-base"]/span[@class="a-size-base a-color-price a-color-price"]|.//a/span[@class="a-price"]/span[@aria-hidden="true"]/span[@class="a-price-whole" and contains(text(),"¥")]|.//span[@class="a-price a-text-price a-size-medium apexPriceToPay" and @data-a-size="b"]/span[2]|.//div[@class="a-section a-spacing-none aok-align-center"]/span[@data-a-color="base"]/span/span[@class="a-price-whole"]|.//span[@class="a-price-whole"]|.//td/span[@id="snsDetailPagePrice"]/span|//span[@id="priceblock_ourprice"]/span',
pointrateXPath: '//div/span[@class="a-size-base a-color-price" and contains(text(),"ポイント(")]|.//span[@class="a-color-price" and contains(text(),"pt")]|.//div/div[@id="points_feature_div"]/span[contains(@class,"a-color-price")]|.//span[@class="a-size-base a-color-price" and contains(text(),"ポイント")]|.//span[@class="a-size-base a-color-base" and contains(text(),"%)")]:visible',
domNIDelay: 1500,
orderPL: 5,
listPL: 5,
isorder: /https?:\/\/order\./,
iscate: /category\//,
isproduct: /\/dp\//,
issearch: /amazon.*?s\?k=|amazon.*?[\?\&]keywords\=|amazon.*?[\?\&]field-keywords\=/,
sortData: [
{ url: /^(?=.*(^(?!.*(\&rh=)).*))(?=.*(https:\/\/www.amazon.co.jp\/s\?k=))/, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: 'div.sg-col-4-of-12.s-result-item', },
{ url: /https:\/\/www.amazon.co.jp\/s\?k=.*\&rh=/, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: 'div.sg-col-4-of-12.s-result-item', },
{ url: /https:\/\/www.amazon.co.jp\/s\?k=.*\&rh=/, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: '.s-result-item.s-asin.sg-col-0-of-12.sg-col-16-of-20.sg-col.s-widget-spacing-small.sg-col-12-of-16', }
],
onLoad: () => {},
onEachItem: (node, titleEle, rndcolor) => {},
pointFunc: (parentEle, price, priceEle, rndcolor, tp) => {
var point = 0;
var pointEle = elegeta(SITE.pointrateXPath, parentEle).filter(e => e.offsetHeight && !(tp.excludeWhenClosestIs && e.closest(tp.excludeWhenClosestIs)))[0]
if (pointEle) {
var pointtext = pointEle.textContent.replace(/\d+ポイント|\,/g, "");
if (pointtext.match(/([0-9]+)\%/)) {
debugEle(pointEle, rndcolor);
var pointPer = Number(pointtext.match(/([0-9,]+)%/)[1] / 100);
}
if (pointPer) {
var point = USE_YODOBASHI_METHOD_IN_AMAZON ? Math.floor(price - (price * (price / (price + price * pointPer)))) : Number(price * pointPer);
var pricef = Math.round(price - point).toLocaleString();
if (enableBeta) { $(`<span class='ignoreMe' style='background-color:#fff0f0;${USE_YODOBASHI_METHOD_IN_AMAZON?"color:#f00;font-weight:blod;":"color:#000;"}font-size:min(75%,15px);'>` + "(還元後:" + "¥" + pricef.toLocaleString() + ")</span>").appendTo(priceEle) }
}
} //else { var point = -1; }
return point;
},
onRun: (node, cppLimit) => {
$('.s-line-clamp-4').css({ '-webkit-line-clamp': '9' });
var titleParentlevelXpathSet = [ // todo:titleとpriceのセットにする
{ b: '.a-section.a-spacing-base', t: '//a[@class="a-link-normal s-link-style a-text-normal"]/span|.//span[@class="a-size-base-plus a-color-base a-text-normal"]' }, // 4列検索結果
{ b: '.a-section.a-spacing-base', t: '//a[@class="a-link-normal s-underline-text s-underline-link-text s-link-style a-text-normal"]/span[@class="a-size-medium a-color-base a-text-normal"]' }, // 4列検索結果
{ b: '.a-section.a-spacing-base', t: '//a/span[@class="a-size-base a-color-base a-text-normal"]' }, // 4列検索結果
{ b: '.s-result-item.s-asin.sg-col-0-of-12.sg-col-16-of-20.sg-col.s-widget-spacing-small.sg-col-12-of-16', t: '//span[@class="a-size-medium a-color-base a-text-normal"]' }, // 1列検索結果
{ b: '.s-result-item.s-asin.sg-col-0-of-12.sg-col-16-of-20.sg-col.s-widget-spacing-small.sg-col-12-of-16', t: '//a[@class="a-link-normal s-underline-text s-underline-link-text s-link-style a-text-normal"]/span[@class="a-size-medium a-color-base a-text-normal"]' }, // 1列検索結果
{ b: '.s-result-item.s-asin.sg-col-0-of-12.sg-col-16-of-20.sg-col.s-widget-spacing-small.sg-col-12-of-16', t: '//a/span[@class="a-size-base a-color-base a-text-normal"]' }, // 1列検索結果
{ b: '#dp-container:not(.a-carousel-col *)', t: '//span[@id="productTitle"]', excludeWhenClosestIs: '.a-carousel-col' }, // /dp/詳細画面のタイトル
// { b: '.a-carousel-card', t: '//div/a[@class="a-link-normal" and @role="link"]/span/div[@aria-hidden="true"]'}, // あなたへのおすすめ x動くが全行入らなくなる
]
//titleParentlevelXpathSet.forEach(c=>elegeta(c.e).forEach(e => {e.style.display = "inline-block"; e.closest('.s-line-clamp-2').style.maxHeight = "auto !important;"})) // 商品名を全行表示する
//titleParentlevelXpathSet.forEach(c => elegeta(c.e).forEach(e => { e.style.display = "inline-block"; })) // 商品名を全行表示する
titleParentlevelXpathSet.forEach(tp => elegeta(tp.t).forEach(e => { e.title = e?.innerText; })) // 商品名にホバーで全行表示する
let titleEleA = [];
for (let tp of titleParentlevelXpathSet) {
for (let box of elegeta(tp.b, document)) {
for (let titleEle of elegeta(tp.t, box)) {
let seido = 100;
if (titleEle.dataset.appm == "c") { continue; } else { titleEle.dataset.appm = "c"; }
var rndcolor = makeRndColor(); // var rndcolor = '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6);
debugEle(titleEle, rndcolor, tp.t);
var title = num(titleEle.textContent);
//本の詳細ならページ単価
if (eleget0('//div/div[@data-category="books"]|//span[@class="nav-a-content" and contains(text(),"Kindle本")]|//a/span[@class="nav-a-content" and @text="本"]')) {
dc("is本詳細ページ")
let qu = eleget0('//ul[@class="a-unordered-list a-nostyle a-vertical a-spacing-none detail-bullet-list"]/li/span/span[contains(text(),"ページ")]')?.textContent || ""
if (qu) {
title = qu;
dc(qu)
}
}
var parentEle = box //titleEle.closest('#dp-container>#ppd') || eleget0('./ancestor::div[contains(@class,"sg-col-4-of-12 s-result-item")]', titleEle);
debugEle(parentEle, rndcolor);
//var pointEle = eleget0(SITE.pointrateXPath, parentEle);
var pointEle = elegeta(SITE.pointrateXPath, parentEle).filter(e => e.offsetHeight && !(tp.excludeWhenClosestIs && e.closest(tp.excludeWhenClosestIs)))[0]
debugEle(pointEle, rndcolor);
var pass1 = 0;
var ryou = title.replace(/\,/gm, "").match(/\D?([0-9\.]+)(ページ|mg|g|G|ml|mL|枚|粒|錠|包|杯|本|回分|回用|個|袋|ml|GB|ペア|組|P|日分|ヶ入|組入|ポート|色|日分|ヶ入|食|巻|入|セット|缶|函)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg|kg|キロ|TB)/);
var sFree = elegeta('//div[@class="a-spacing-base"]/a[@target="AmazonHelp" and contains(text(),"無料配送")]|.//span[@data-csa-c-type="element" and @data-csa-c-delivery-price="無料"]|.//div/div[@class="a-section"]/div/div/span/a[@rel="noopener" and text()="無料配送"]:visible', parentEle).filter(e => !(tp.excludeWhenClosestIs && e.closest(tp.excludeWhenClosestIs)))[0]
var sCharge = elegeta('//span[@class="a-color-base" and contains(text(),"配送料 ¥")]|.//div[@class="a-spacing-base" and @id="mir-layout-DELIVERY_BLOCK-slot-PRIMARY_DELIVERY_MESSAGE_LARGE"]/span[contains(text(),"配送料")]|.//span[@class="a-size-mini a-color-base" and @dir="auto" and contains(text(),"送料: ¥")]|.//span[@class="a-color-secondary s-light-weight-text" and contains(text(),"配送料 ¥")]:visible', parentEle).filter(e => !(tp.excludeWhenClosestIs && e.closest(tp.excludeWhenClosestIs)))[0]
var shippingEle = !sFree && sCharge
debugEle(sFree || sCharge, rndcolor)
var priceEle = elegeta(SITE.priceXPath + ":visible", parentEle).filter(e => !(tp.excludeWhenClosestIs && e.closest(tp.excludeWhenClosestIs)))[0]
debugEle(priceEle, rndcolor);
if (priceEle) {
var shipping = shippingEle ? Number(shippingEle.innerText.match0(/[0-9,]+/)?.replace(/\\|¥|\,/g, "")) || 0 : 0
var price = priceEle ? Number(priceEle.innerText.match0(/[0-9,]+/)?.replace(/\\|¥|\,/g, "")) || 0 : 0 //Number(priceEle.textContent.replace(/[^0-9]/g, ""));
var point = SITE.pointFunc(parentEle, price, priceEle, rndcolor, tp);
if (title.match(/クッキングシート/)) var ryou = title.replace(/\,/gm, "").match(/\D([0-9\.]+)(m|g|G|枚|粒|錠|包|杯|本|個|袋|GB|ペア|組|P|日分|ヶ入|組入|ポート|色|日分|ヶ入|食|巻|入|セット|缶|函)|(?:[^A-Z0-9\.\-])([0-9\.]+)(L|kg|㎏|Kg|KG|kg|キロ|TB)/);
if (ryou) {
if (ryou[4]) { ryou[4] = ryou[4].replace(/kg|㎏|Kg|KG|kg|キロ/, "g").replace(/L/, "ml").replace(/TB/, "GB"); }
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
if (title.match(/×[0-9\.\,]+/m) && !(title.match(/[\((\[【].*×.*[\))\]】]/m)) && !(title.match(/×[\d\s]*(cm|mm|g)/))) { ryout *= Number(title.match(/×([0-9\.\,]+)/)[1]); }
if (title.match(/mg.+[0-9\.\,]+(粒|錠)/m)) {
ryout *= Number(title.match(/([0-9\.\,]+)(粒|錠)/)[1]);
seido = 10000;
}
var mul = 1;
if (point) { var priceEle = eleget0(SITE.priceXPath, parentEle); if (priceEle) { priceEle.dataset["ppr"] = Number(price + shipping - (point || 0)); } }
var ppr = Math.round(seido * (price + shipping - point) / Number(ryout * mul)) / seido;
var pprEmbed = (price + shipping - point) / Number(ryout * mul);
var ele = $(`<span class="ignoreMe ppr" data-ppr="${ pprEmbed }" style="background-color:#${shipping?"60a090":"6080b0"};">¥${ ppr}/${(ryou[2] || ryou[4]) }</span>`).insertAfter(titleEle.parentNode.parentNode);
if ((!isproduct) && (!isorder)) { setClick(ele, ppr, "(\\" + (Math.round(price - point)) + "+\\" + shipping + ")/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n"); } else { $(ele).attr("title", "(\\" + (Math.round(price - point)) + "+\\" + shipping + ")/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n"); }
//if (cppLimit[1] > 0 && (!priceEle || !ryou || (ppr && cppLimit[1] < ppr))) debugRemove(parentEle); // ancest
if (cppLimit[1] > 0 && (!priceEle || !ryou || (ppr && cppLimit[1] < ppr))) debugRemove(parentEle?.closest('div[data-asin]') || parentEle); // ancest
}
}
// if (cppLimit[1] > 0 && (!priceEle || !ryou || (ppr && cppLimit[1] < ppr))) debugRemove(parentEle); // ancest
}
}
}
},
},
// -----------------------------------------------------
{
is: 'IHERB',
urlRE: 'jp.iherb.com/',
titleXPath: '//a[@class="absolute-link product-link"]|.//section[3]/div[@id="product-summary-header"]/h1|//section/div/div[@id="name"]',
priceXPath: '//span[@class="price "]/bdi|.//div[1]/span[@class="price discount-red"]/bdi|.//div[@id="price"]|.//div[1]/span[@class="price discount-green"]/bdi|//div[@id="price"]',
orderPL: 5,
listPL: 5,
isorder: /https?:\/\/order\./,
iscate: /category\/|\/c\//,
isproduct: /\/pr\//,
issearch: /search/,
sortData: [
{ url: /https:\/\/jp.iherb.com\/search\?kw\=|https:\/\/jp.iherb.com\/c\//, sortPpr: '//span[@class="ignoreMe ppr2"]', sortElement: '.product-cell-container', },
{ url: /https:\/\/jp.iherb.com\/search\?kw\=|https:\/\/jp.iherb.com\/c\//, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: '.product-cell-container' }
],
onLoad: () => {},
onEachItem: (node, titleEle, rndcolor) => {},
pointFunc: (parentEle, price, priceEle, rndcolor) => {},
hide: (title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle) => {
// console.log(isorder, issearch, iscate, isproduct);
// type1
let seido = 100;
var pass1 = 0;
var ryou = title.replace(/\,/g, "").match(/\D([0-9\.]+)\s?(mg|g|ml|mL|mcg)|\D([0-9\.]+)(L|kg)/);
let discreteUnit = /\D([0-9\.]+)\s?(Pack|枚|タブレット|カプセル|個|錠|ベジタリアンカプセル|ベジタブルカプセル|植物性カプセル|Vegan.*Caps|Softgel.*Capsule|ベジ.*キャップ|ジェルキャップ|Veggie Caps|液.*ジェル|ソフトゲル|ビーガンタブレット|ゼラチンカプセル|ベジソフトジェル|Veg Capsules|ベジカプセル|べジカプセル|カプセル|粒|ベジキャップ|チュアブル錠|ソフトゼリー|ティーバック|ティーバッグ|袋|Softgels|ソフトジェル|Chewable Tablets|錠|Tablets|グミ|ロゼンジ|植物性液体フィトカプセル|Vegetarian Capsules|Vegetarian Food-Based Tablets|Caples|Vegi-Caps|Capsules|Mini Soft Gels)/m;
if (ryou && (ryou[1] > 0 || ryou[3] > 0)) {
if (ryou[4]) ryou[4] = ryou[4].replace(/kg|㎏|Kg/, "g").replace(/L/, "ml"); //.replace(/TB/, "GB");
var ryout = Number(ryou[1]) || Number(ryou[3]) * 1000;
var mul = (title.match(discreteUnit)) ? Number(title.match(discreteUnit)[1]) : 1;
if (title.match(discreteUnit)) seido = 10000;
var ppr = Math.round(seido * (price) / Number(ryout * mul)) / seido;
var pprEmbed = (price) / Number(ryout * mul);
//var ppr = Math.round(100 * (price) / Number(ryout * mul)) / 100;
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbed + '" style=" position:relative;z-index:999; display:inline-block; font-weight:bold; font-size:15px;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr + '/' + (ryou[2] || ryou[4]) + (ppr == undefined ? ryou + "," + ryout + "," + mul : "") + '</span>').insertAfter(titleEle.parentNode);
if ((!isproduct) && (!isorder)) setClick(ele, ppr, "\\" + (Math.round(price)) + "/" + Number(ryout * mul) + (ryou[2] || ryou[4]) + "=" + pprEmbed + "\n");
pass1 = ((iscate || issearch) && cppLimit[1] && ppr <= cppLimit[1]) ? 1 : 0;
}
// type2
var pass2 = 0;
var ryou1 = ryou;
var ryou = title.match(discreteUnit);
if (ryou && (ryou[1] > 0)) {
var ryout = Number(ryou[1]);
var mul = 1;
var ppr2 = Math.round(100 * (price) / Number(ryout * mul)) / 100;
titleEle.style.display = "inline";
var ele = $('<span class="ignoreMe ppr2" style=" position:relative;z-index:999; display:inline-block; font-weight:bold; font-size:15px;margin:0.5px 0px 0.5px 3px; text-decoration:none !important; padding:0.03em 0.5em 0.03em 0.2em; border-radius:99px; background-color:#6080b0; color:white; white-space: nowrap; ">¥' + ppr2 + '/' + (ryou[2] || ryou[4]) + '</span>').insertAfter(titleEle.parentNode);
if ((!isproduct) && (!isorder)) $(ele).css("cursor", "pointer").attr("title", "クリックかShift+Bでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 2, ppr2));
pass2 = ((iscate || issearch) && cppLimit[2] && ppr2 <= cppLimit[2]) ? 1 : 0;
}
if ((cppLimit[1] > 0 && pass1 == 0) || (cppLimit[1] > 0 && (!ryou1))) debugRemove(parentEle.parentNode);
if ((cppLimit[2] > 0 && pass2 == 0) || (cppLimit[2] > 0 && (!ryou))) debugRemove(parentEle.parentNode);
},
},
];
// -----------------------------------------------------
var siteinfo = SITEINFO;
// var siteinfo = Object.assign(SITEINFO, pref("MY_SITEINFO") || []); //alert(siteinfo);return;
// thissiteを決定
var thissite = null;
for (var i = 0; i < siteinfo.length; i++) {
if (siteinfo[i].urlRE == "") break;
if (location.href.match(siteinfo[i].urlRE)) {
thissite = i;
var SITE = Object.create(siteinfo[thissite]);
break;
}
}
if (thissite === null) return;
function sta(str, pointer = 0) { // 右下ステータス表示
return $('<span style=" ' + (pointer ? 'cursor:pointer; ' : '') + 'position: fixed; right:1em; bottom: ' + (gStaY += 2.5) + 'em; z-index:2147483647; opacity:1; font-size:15px; font-weight:bold; margin:0px 1px; text-decoration:none !important; text-align:center; padding:1px 6px 1px 6px; border-radius:12px; background-color:#6080ff; color:white; white-space: nowrap; ">' + str + '</span>').appendTo(document.body);
}
if (debug) sta("debug1");
if (debug2) sta("debug2");
var cppLimit = [0, 0];
if (SITE.onLoad) SITE.onLoad();
var isorder = location.href.match(SITE.isorder);
var issearch = location.href.match(SITE.issearch);
var iscate = location.href.match(SITE.iscate);
var isproduct = location.href.match(SITE.isproduct);
var parentLimit = isorder ? SITE.orderPL : SITE.listPL;
function inputcpplimit(e, type, autonumber = null) {
e.stopPropagation();
e.preventDefault();
var ret = proInput("量あたり価格上限を入力してください", autonumber || cppLimit[type]);
if (ret === null || ret == cppLimit[type]) return false;
cppLimit[type] = ret;
sessionStorage.setItem("cppLimit" + type, cppLimit[type] || "") || 0;
location.reload();
return false;
}
if (issearch || iscate) {
cppLimit[1] = sessionStorage.getItem("cppLimit1") || 0;
if (cppLimit[1]) $(sta("limit1(Shift+A): " + cppLimit[1], 1)).appendTo(document.body).attr("title", "クリックかShift+Aでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 1));
cppLimit[2] = sessionStorage.getItem("cppLimit2") || 0;
if (cppLimit[2]) $(sta("limit2(Shift+B): " + cppLimit[2], 1)).appendTo(document.body).attr("title", "クリックかShift+Bでこの量単価の上限で絞り込む").click(e => inputcpplimit(e, 2));
document.addEventListener("keydown", function(e) {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.getAttribute('contenteditable') === 'true' || ((e.target.closest('#chat-messages,ytd-comments-header-renderer') || document.activeElement.closest('#chat-messages,ytd-comments-header-renderer')))) return;
var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key;
if (key == "Shift+A") inputcpplimit(e, 1); // shift+a 量あたり価格上限
if (key == "Shift+B") inputcpplimit(e, 2); // shift+b 量あたり価格上限
if (key == "a") {
lh(/amazon/) && elegeta('//div[@class="s-result-item sg-col-0-of-12 sg-col-16-of-20 s-widget sg-col s-flex-geom sg-col-12-of-16 s-widget-spacing-large"]').forEach(e => e.remove()) // おすすめ記事
sortByPpr(); // a::量単価小さい順で並べ替え
}
if (key == "Shift+Alt+A") {
e.preventDefault();
if (lh(/amazon/)) {
lh(/amazon/) && elegeta('//div[@class="s-result-item sg-col-0-of-12 sg-col-16-of-20 s-widget sg-col s-flex-geom sg-col-12-of-16 s-widget-spacing-large"]').forEach(e => e.remove()) // おすすめ記事
sortEle(elegeta('div[data-asin]').map(e => eleget0('.a-price-whole', e)).filter(c => c), '.s-result-item', /https:\/\/www.amazon.co.jp\/s\?k=/);
}
if (lh(/yodobashi/)) domsort(eleget0('#listContents'), elegeta('.pListBlock'), (v) => { return parseInt(v.querySelector('.productPrice>span').innerText.replace(/\D/g, "")) }, 1)
}
},
false);
}
setTimeout(() => { run(document); }, document.hidden ? 0 : (SITE.domNIDelay || 100));
document.body.addEventListener('DOMNodeInserted', function(evt) { setTimeout(() => { run(evt.target); }, SITE.domNIDelay || 100); }, false);
return;
function sortByPpr() {
if (SITE.sortData && location.href.match(SITE.sortUrl)) SITE.sortData.forEach(e => { sortEle(e.sortPpr, e.sortElement, "useppr") });
if (SITE.onSort) SITE.onSort()
return;
}
function sortEle(xpath, close, opt = null) {
// let p = (typeof xpath != "string" ? xpath : elegeta(xpath)).filter(e => e.offsetHeight > 0 && e.closest(close));
let p = (typeof xpath != "string" ? xpath : elegeta(xpath + ":visible")).filter(e => e.closest(close));
let pele = p.map(e => e.closest(close))
//if (debug) p.forEach(e => debugEle(e,"#f00"))//e.style.backgroundImage = "radial-gradient(#aaa,#999)")//"radial-gradient(#c7a,#329)") //" -webkit-gradient(linear, left top, right top, from(#329), to(#47a))")
if (!p || !pele || p.length == 0 || pele.length == 0 || p.length != pele.length) return;
pele.forEach((e, i) => {
e.pr = opt == "useppr" && p[i].dataset.ppr ? Number(p[i].dataset.ppr) : Number(p[i]?.innerText?.replace(/\,/gm, "")?.match0(/[0-9.]+/));
//if(debug) e.insertAdjacentHTML("beforeend", ` pr:\\${e.pr}`)
});
let pele2 = pele.slice();
pele2 = pele2.sort((a, b) => { return Number(a.pr) > Number(b.pr) ? 1 : -1 });
pele.forEach((e, i) => { e.outerHTML = pele2[i].outerHTML })
}
function setClick(ele, ppr, shiki = "") {
$(ele).css("cursor", "pointer").attr("title", shiki + "クリックかShift+Aでこの量単価の上限で絞り込む\n右クリックかAキーで量単価で並べ替え").click(e => inputcpplimit(e, 1, ppr)).on("contextmenu", e => {
sortByPpr();
e.preventDefault();
return false;
});
}
function run(node) {
if (!node || node.nodeName === "#text") return;
if (node.classList && node.classList.contains("ignoreMe")) return;
//if (debug) console.log(node);
if (SITE.onRun) { SITE.onRun(node, cppLimit); return; }
// onRunがなかったら
for (let titleEle of elegeta(SITE.titleXPath, node)) {
var rndcolor = makeRndColor(); // var rndcolor = '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6);
var title = (titleEle.title ? titleEle.title : titleEle.textContent);
if (titleEle.dataset.yCpP) { continue; } else { titleEle.dataset.yCpP = "1"; }
if (debug) debugEle(titleEle, rndcolor);
var parentEle = titleEle;
if (SITE.onEachItem) SITE.onEachItem(node, titleEle, rndcolor);
for (var i = 0; i < parentLimit; i++) {
parentEle = parentEle.parentNode;
let found = elegeta(SITE.priceXPath, parentEle).length;
if (found == 1) break;
if (found > 1) i = parentLimit + 1;
}
if (i > parentLimit) continue;
debugEle(parentEle, rndcolor);
if (i == parentLimit) continue;
var priceEle = eleget0(SITE.priceXPath, parentEle);
if (!priceEle) continue;
debugEle(priceEle, rndcolor);
var price0 = (priceEle.textContent.replace(/[A-Za-z0-9]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 0xFEE0) }))
var price = Number(price0.match(/\D?([0-9\,]+)/)[1].replace(/\,/g, ""));
if (SITE.pointFunc) var point = SITE.pointFunc(parentEle, price, priceEle, rndcolor);
if (SITE.hide) SITE.hide(title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle);
}
}
}
function elegeta(xpath, node = document) {
if (!xpath) return [];
let flag
if (!/^\.?\//.test(xpath)) return /:visible$/.test(xpath) ? [...node.querySelectorAll(xpath.replace(/:visible$/, ""))].filter(e => e.offsetHeight) : [...node.querySelectorAll(xpath)]
try {
var array = [];
var ele = document.evaluate("." + xpath.replace(/:visible$/, ""), node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
let l = ele.snapshotLength;
for (var i = 0; i < l; i++) array[i] = ele.snapshotItem(i);
return /:visible$/.test(xpath) ? array.filter(e => e.offsetHeight) : array;
} catch (e) { popup3(e + "\n" + xpath, 1); return []; }
}
function eleget0(xpath, node = document) {
if (!xpath) return null;
if (!/^\.?\//.test(xpath)) return node.querySelector(xpath.replace(/:visible$/, ""));
try {
var ele = document.evaluate("." + xpath.replace(/:visible$/, ""), node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
return ele.snapshotLength > 0 ? ele.snapshotItem(0) : "";
} catch (e) { popup3(e + "\n" + xpath, 1); return null; }
}
function proInput(prom, defaultval, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
var inp = window.prompt(prom, defaultval);
if (inp === undefined || inp === null) return inp;
return Math.min(Math.max(Number(inp.replace(/[A-Za-z0-9.]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 65248); }).replace(/[^-^0-9^\.]/g, "")), min), max);
}
function makeRndColor() {
return '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6);
//return '#' + ([0,0,0].map(c=>"789abcdef"[Math.floor(Math.random()*9)])).join("");
}
function debugEle(ele, col = "random", additionalInfo = "") {
if (ele && (debug || col.indexOf("forced") !== -1)) {
if (col.indexOf("random") !== -1) col = '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6);
// if (col.indexOf("random") !== -1) col = '#' + ("000".map(c=>"89abcdef"[Math.random()*8]));
ele.style.outline = "3px dotted " + col;
ele.style.boxShadow = " 0px 0px 4px 4px " + col + "30, inset 0 0 100px " + col + "20";
ele.dataset.yododebugele = ""
//ele.outerHTML+=additionalInfo;
}
}
function debugRemove(ele) {
if (debug2) { ele.style.opacity = "0.5"; } else ele.remove();
}
function num(str) {
return str.replace(/[A-Za-z0-9.]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 65248); });
}
function dc(str, force = 0) {
if (debug >= 1 || force) popup3(str, 0, 5000, "top");
return str;
}
function popup3(text, i = 0, timer = 15000, alignY = "bottom") {
if (text === undefined || text === null) text = "<null>"
if (typeof text == "string") text = text.slice(0, 200);
if (typeof text == "number") text = String(text);
text = text.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/`/g, '`').replace(/</g, "<").replace(/>/g, ">").replace(/\n/gm, "<br>")
let id = Math.random().toString(36).substring(2);
let maey = alignY == "bottom" ? 0 : elegeta(".amaqpu3top").map(e => e.getBoundingClientRect().bottom).reduce((a, b) => Math.max(a, b), 0) + 2;
if (i > 0) $(`.pu3line${i}s`).remove()
var ele = $(`<span id="amaqpu3${id}" class="ignoreMe amaqpu3${alignY} pu3line${i}s" style=" max-width:33%;font-family:sans-serif; position: fixed; right:0em; ${ alignY }:${((maey) + i * 18)}px; z-index:2147483647; opacity:1; font-size:15px; margin:0px 1px; text-decoration:none !important; padding:1px 6px 1px 6px; word-break: break-all !important; border-radius:12px; background-color:#10804f; color:white; ">${ text }</span>`).appendTo('body');
let ey = ele[0]?.getBoundingClientRect()?.height
if (ele[0].getBoundingClientRect().bottom >= (window.innerHeight)) {
elegeta('.amaqpu3top').forEach(e => { e.style.top = parseFloat(e?.style?.top) - (ey) - 2 + "px" })
}
if (typeof text == "string") { maey += (text.match(/<br>/gmi) || []).length || 0; } //console.log((text.match(/<br>/gmi) || [] ).length) }
setTimeout(() => {
eleget0('//span[@id="amaqpu3' + id + '"]')?.remove();
}, timer);
}
function isinscreen(ele, evencorner = 0, borderHeight = 0) {
if (!ele) return;
var eler = ele.getBoundingClientRect();
if (evencorner) return (eler.top > 0 - eler.height - borderHeight && eler.left > 0 && eler.left < document.documentElement.clientWidth && eler.top < Math.min(window.innerHeight, document.documentElement.clientHeight) + borderHeight);
else return (eler.top > 0 - 0 && eler.left > 0 && eler.left + eler.width < document.documentElement.clientWidth && eler.top + eler.height < Math.min(window.innerHeight, document.documentElement.clientHeight) + 0);
}
function lh(re) { let tmp = location.href.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可
//newstr.sort(new Intl.Collator("ja", {numeric: true, sensitivity: 'base'} ).compare )
function domsort(container, doms, func, prepend = 0) { // prepend:1ならcontainerの最初に付ける、0なら最後に付ける
doms.map(function(v) { dc(func(v)); return { dom: v, value: func(v) } }).sort(function(a, b) { return (typeof Number(a.value) && Number(b.value) ? (b.value - a.value) : (a.value < b.value ? 1 : -1)) }).forEach(function(v) { prepend ? container.prepend(v.dom) : container.appendChild(v.dom); });
}
})();