Greasy Fork

来自缓存

Greasy Fork is available in English.

ヨドバシ検索結果で量あたり単価を表示

Shift+A/Shift+B:量単価上限で絞り込み A:量単価昇順 .:価格上限入力フォームにフォーカス Shift+Alt+A:価格昇順 z:レビューの★多い順 ,:価格上限で絞り込み(Amazon,iHerb)

当前为 2024-01-03 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name ヨドバシ検索結果で量あたり単価を表示
// @description Shift+A/Shift+B:量単価上限で絞り込み A:量単価昇順 .:価格上限入力フォームにフォーカス Shift+Alt+A:価格昇順 z:レビューの★多い順 ,:価格上限で絞り込み(Amazon,iHerb)
// @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/*
// @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/*
// @match https://nttxstore.jp/freeSearch*
// @match https://nttxstore.jp/_II_*
// @match https://search.rakuten.co.jp/*
// @match https://sundrug-online.com/collections/*
// @match https://sundrug-online.com/products/*
// @match https://sundrug-online.com/search*
// @match https://www1.pcdepot.co.jp/products/list*
// @match https://www1.pcdepot.co.jp/products/detail/*
// @match https://www.topvalu.net/items/*
// @match https://www.topvalu.net/search/*
// @match *://auctions.yahoo.co.jp/*
// @match *://page.auctions.yahoo.co.jp/jp/auction/*
// @noframes
// @grant       GM_addStyle
// @version 0.4.7
// @run-at document-idle
// @namespace http://greasyfork.icu/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:計算に使った要素を常に可視化 0:通常モード
  const USE_YODOBASHI_METHOD_IN_AMAZON = 1; // 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

  var GF = {}
  if (engine2() != "not target") return;

  String.prototype.match0 = function(re) { let tmp = this.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可


  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(?!b)|kg|㎏|Kg)/); // /\D([0-9\.]+)\s?(mg|g|ml|mL|mcg)|\D([0-9\.]+)(L(?!b)|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;
          }
          /*
                    // 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 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);
                      //            var ele = $('<span class="ignoreMe ppr2" >¥' + ppr2 + '/' + (ryou[2] || ryou[4]) + '</span>').insertAfter(titleEle.parentNode);
                      var ele = $('<span class="ignoreMe ppr2" >¥' + 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 ((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(?!b)|kg|㎏|Kg)/); // /\D([0-9\.]+)\s?(mg|g|ml|mL|mcg)|\D([0-9\.]+)(L(?!b)|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]|//span[contains(@class,"yhmMyMemo")]',
        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]',
        //titleXPath: '.yhmMyMemo',
        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\/|\/maker\//,
        isproduct: /\/product\//,
        orderPL: 5,
        listPL: 3,
        //        closest:'.srcResultItem_block,.pListBlock,.js_productBox,.js_smpClickable,.js_latestSalesOrderProduct,.productListTile',//srcResultItem_block pListBlock hznBox js_productBox js_smpClickable js_latestSalesOrderProduct  productListTile
        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=|\/\/www.yodobashi.com\/maker\//, // 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.isContentEditable || ((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 || pointPer === 0) {
              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(?!b)|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(?!b)|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/', //|//www.kohnan-eshop.com/shop/g/',
        titleXPath: '//a[@class="js-enhanced-ecommerce-goods-name"]|//h1[@class="block-goods-name js-enhanced-ecommerce-goods-name"]', //'|//div[@class="mainframe_"]/h1[@class="goods_name_"]',
        priceXPath: '//div[@class="block-thumbnail-t--price-items"]/div|//div/div[@class="block-cartbox-section--price-price"]', //'|//table[@class="formdetail_ goodsspec_"]/tbody/tr[5]/td/span[@class="price_"]',        orderPL: 3,
        listPL: 3,
        isorder: /$^/,
        iscate: /shop\/c\//,
        isproduct: /www.kohnan-eshop.com\/shop\/g\//,
        issearch: /search/,
        sortData: [{ url: /https:\/\/www.kohnan-eshop.com\/shop\/goods\/search.aspx|\/\/www\.kohnan-eshop\.com\/shop\//, sortPpr: '//span[@class="ignoreMe ppr"]', sortElement: '.block-thumbnail-t li', }],
        //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(?!b)|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\=/,
        issearch: /amazon.*?s\?|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);' title='ポイント率:${pointPer}\nポイント:${point}'>` + "(還元後:" + "¥" + pricef.toLocaleString() + ")</span>").appendTo(priceEle) }
              if (enableBeta && !parentEle?.dataset?.kangengo) {
                $(`<span class='ignoreMe' style='background-color:#fff0f0;${USE_YODOBASHI_METHOD_IN_AMAZON?"color:#f00;font-weight:blod;":"color:#000;"}font-size:min(75%,15px);' title='ポイント率:${pointPer}\nポイント:${point}'>` + "(還元後:" + "¥" + pricef.toLocaleString() + ")</span>").appendTo(priceEle);
                parentEle.dataset.kangengo = 1
              }
            }
          } //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: 'div.a-section.a-spacing-none.a-spacing-top-small.s-title-instructions-style a.a-link-normal.s-underline-text.s-underline-link-text.s-link-style.a-text-normal' }, // 4列検索結果
            //{ 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(?!b)|kg|㎏|Kg|kg|キロ|TB)/);
                var ryou = title.replace(/\,/gm, "").match(/\D?([0-9\.]+)\s?(ページ|mg|g|G|ml|mL|枚|粒|錠|包|杯|本|回分|回用|個|袋|ml|GB|ペア|組|P|日分|ヶ入|組入|ポート|色|日分|ヶ入|食|巻|入|セット|缶|函)|(?:[^A-Z0-9\.\-])([0-9\.]+)\s?(L(?!b)|kg|㎏|Kg|kg|キロ|TB)/); // 1,200 gのように数字と単位の間に1つのスペースを許容

                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[contains(@class,"a-color-secondary") and contains(text(),"配送料 ¥")]|.//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(),"配送料 ¥")]|.//span[contains(@class,"a-color-secondary puis-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(?!b)|kg|㎏|Kg|KG|kg|キロ|TB)/);
                  if (title.match(/ケーブル/)) var ryou = title.replace(/\,/gm, "").match(/\D([0-9\.]+)(枚|粒|錠|包|杯|本|個|袋|ペア|組|P|日分|ヶ入|組入|ポート|色|日分|ヶ入|食|巻|入|セット|缶|函)/);
                  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.s-asin[data-asin]') || parentEle); // ancest
                    //                    if (price && priceLimit && price>priceLimit) debugRemove(parentEle?.closest('div.s-asin[data-asin]') || parentEle); // ancest
                  }
                  //if (price && priceLimit && price > priceLimit) debugRemove(parentEle?.closest('div.s-asin[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"]',
        //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[@class="price-inner-text" and @style="display: flex;"]',
        priceXPath: '//span[@class="price "]/bdi|.//span[@class="price discount-red"]/bdi|.//label[1]/section/section/div[@class="row"]/div[last()]/div[@class="price-inner-text"]/p|.//div/div[@id="price"]/div[2]/p',
        //      priceXPath: '//span[@class="price "]/bdi|.//div[1]/span[@class="price discount-red"]/bdi|.//div[1]/span[@class="price discount-green"]/bdi|//div[@class="price-inner-text"]|//label[1]/section/section/div[@class="row"]/div[last()]/div[@class="price-inner-text"]/p',

        //priceXPath: '//span[@class="price "]/bdi|.//div[1]/span[@class="price discount-red"]/bdi|.//div[1]/span[@class="price discount-green"]/bdi|//div[@class="price-inner-text"]',
        close: () => { return '.product-cell-container,div.product-detail-container.ga-product.clearfix,div.product-card.product.ga-product' },
        orderPL: 5,
        listPL: 6,
        isorder: /https?:\/\/order\./,
        iscate: /category\/|\/c\/|\/specials|\/trial-pricing/,
        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(?!b)|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 pprEmbedAligned = pprEmbed
            if (ryou[2]?.match(/mg/i)) pprEmbedAligned = (price) / Number(ryout * mul / 1000)
            if (ryou[2]?.match(/mcg/i)) pprEmbedAligned = (price) / Number(ryout * mul / 1000 / 1000)
            titleEle.style.display = "inline";
            var ele = $('<span class="ignoreMe ppr" data-ppr="' + pprEmbedAligned + '" 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);
            //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, y = 0, id = null) { // 右下ステータス表示
      if (id) $(`#${id}`).remove()
      return str > "" ? $(`<span ${id?`id="${id}"`:""} style="${(pointer ? 'cursor:pointer; ' : '')} position: fixed; right:1em; bottom:${(y* 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", 0, 1);
    if (debug2) sta("debug2", 0, 2);
    let priceLimit = sessionStorage.getItem("priceLimit") || null;
    if (priceLimit) {
      /*popup3("");
      sta(`,:価格上限で絞り込み(¥${priceLimit})`, 4)*/
    }

    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, 3)).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, 4)).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.isContentEditable || ((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 量価格上限a
          if (key == "Shift+B") inputcpplimit(e, 2); // shift+b 量価格上限b
          if (key == "z") { //z::レビューの★多い順
            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"]|//div[@class="a-section a-spacing-none s-shopping-adviser s-shopping-adviser-line-clamp-ie"]').forEach(e => e.remove()) // おすすめ記事
              sortdom(elegeta('div.s-asin[data-asin]'), v => { return (((eleget0('//span[contains(text(),"5つ星のうち")]', v)?.textContent?.trim()?.match(/5つ星のうち([0-9\.]+)/)?.[1] || 0))) }, 1)
              popup3(`z:レビューの★多い順に並べ替え\nこのバルーンをクリックするとさらに価格のない商品を隠します`, 8, 5000, "bottom", () => { elegeta('div.s-asin[data-asin]').filter(e => !eleget0('.a-price-whole', e)).forEach(e => $(e).hide(666)) })
            }
            if (lh(/yodobashi/)) {
              sortdom(elegeta('#listContents .pListBlock'), v => { return ((parseFloat(eleget0('div.valueAvg>a', v)?.className?.match0(/rate(\d+_\d+)/)?.replace(/_/, ".")) * 1000000) + ((+eleget0('//div[@class="valueAvg"]/span[@class="fs11 alignM"]/a', v)?.textContent))) || 0 }, 1)
              popup3(`z:レビューの★多い順に並べ替え`, 8, 5000, "bottom", () => { elegeta('div.s-asin[data-asin]').filter(e => !eleget0('.a-price-whole', e)).forEach(e => $(e).hide(666)) })
            }
          }
          if (key == "a") { //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"]|//div[@class="a-section a-spacing-none s-shopping-adviser s-shopping-adviser-line-clamp-ie"]').forEach(e => e.remove()) // おすすめ記事

            if (lh(/amazon/)) {
              sortdom(elegeta('div.s-asin[data-asin]'), v => { return (((eleget0('.ppr', v)?.textContent?.match0(/([0-9\.]+)/)?.trim()))) || 999 }, 0)
              popup3(`a:両単価が安い順に並べ替え をしました\nこのバルーンをクリックするとさらに価格のない商品を隠します`, 8, 5000, "bottom", () => { elegeta('div.s-asin[data-asin]').filter(e => !eleget0('.a-price-whole', e)).forEach(e => $(e).hide(666)) })
            } else {
              sortByPpr();
              //              popup3(`a:両単価が安い順に並べ替え`, 8, 5000, "bottom")
            } // 量単価小さい順で並べ替え
          }
          if (key == "Shift+Alt+A") { // Shift+Alt+A::
            e.preventDefault();
            if (lh(/\/\/www\.amazon\.co\.jp\//)) {
              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.s-asin[data-asin]').map(e => eleget0('.a-price-whole', e)).filter(c => c), '.s-result-item', /https:\/\/www.amazon.co.jp\/s\?k=/);
              popup3("");
              popup3(`Shift+Alt+A:安い順に並べ替え をしました\nこのバルーンをクリックするとさらに価格のない商品を隠します`, 8, 5000, "bottom", () => { elegeta('div.s-asin[data-asin]').filter(e => !eleget0('.a-price-whole', e)).forEach(e => $(e).hide(666)) })
            }
            if (lh(/\/\/jp\.iherb\.com\//)) {
              domsort(eleget0('div.products.clearfix'), elegeta('.product-cell-container'), (v) => { return parseInt(eleget0('//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"]', v)?.innerText?.replace(/\D/g, "") || 0) }, 1)
              popup3("");
              popup3(`Shift+Alt+A:安い順に並べ替え`, 8)
            }
            if (lh(/\/\/www\.yodobashi\.com\//)) {
              domsort("", elegeta('#listContents .pListBlock'), (v) => { return parseInt(eleget0('#listContents .productPrice>span', v)?.innerText?.replace(/\D/g, "") || 0) }, 1)
              popup3("");
              popup3(`Shift+Alt+A:安い順に並べ替え`, 8)
            }
            if (ld("iherb.")) {
              domsort("", elegeta('//div[@class="product-cell-container col-xs-12 col-sm-12 col-md-8 col-lg-6"]'), (v) => { return parseInt(eleget0('div.product-price-top', v)?.innerText?.replace(/\D/g, "") || 0) }, 1)
              popup3("");
              popup3(`Shift+Alt+A:安い順に並べ替え`, 8)
            }
          }
          if (key == "," && ld(/iherb/)) { // ,::価格上限で絞り込み
            priceLimit = proInput(`,:上限価格を入力してください`, priceLimit || 0) || 0; // , 価格上限
            sessionStorage.setItem("priceLimit", priceLimit || "") || 0;
            //popup3("");
            sta(priceLimit > 0 ? `,:価格上限で絞り込み(¥${priceLimit})` : "", 0, 5, "comma")
            moq("div.product-cell-container", eles => setTimeout(() => {
              /*              eles.filter(v => priceLimit != 0 && (!eleget0('div.product-price-top', v) || eleget0('div.product-price-top', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit)).forEach(v => $(v).hide(999))
                            eles.filter(v => priceLimit == 0 || (!(!eleget0('div.product-price-top', v) || eleget0('div.product-price-top', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit))).forEach(v => $(v).show(999))
              */
              eles.filter(v => priceLimit != 0 && (!eleget0('div.product-price-top', v) || eleget0('div.product-price-top', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit)).forEach(v => {
                gmDataList_add(v, "gmHideByyodoComma");
                $(v).hide(999)
              })
              eles.filter(v => priceLimit == 0 || (!(!eleget0('div.product-price-top', v) || eleget0('div.product-price-top', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit))).forEach(v => { gmDataList_remove(v, "gmHideByyodoComma"); if (!gmDataList_includesPartial(v, 'gmHideBy')) $(v).show(999) })
            }, 999))
            return false
          }
          if (key == "," && ld(/amazon/)) { // ,::価格上限で絞り込み
            priceLimit = proInput(`,:上限価格を入力してください`, priceLimit || 0) || 0; // , 価格上限
            sessionStorage.setItem("priceLimit", priceLimit || "") || 0;
            //popup3("");
            sta(priceLimit > 0 ? `,:価格上限で絞り込み(¥${priceLimit})` : "", 0, 5, "comma")
            moq("div.s-asin[data-asin]", eles => setTimeout(() => {
              /*              eles.filter(v => priceLimit != 0 && (!eleget0('.a-price-whole', v) || eleget0('.a-price-whole', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit)).forEach(v => $(v).hide(999))
                            eles.filter(v => priceLimit == 0 || (!(!eleget0('.a-price-whole', v) || eleget0('.a-price-whole', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit))).forEach(v => $(v).show(999))
              */
              eles.filter(v => priceLimit != 0 && (!eleget0('.a-price-whole', v) || eleget0('.a-price-whole', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit)).forEach(v => {
                gmDataList_add(v, "gmHideByyodoComma");
                $(v).hide(999)
              })
              eles.filter(v => priceLimit == 0 || (!(!eleget0('.a-price-whole', v) || eleget0('.a-price-whole', v)?.textContent?.match(/([0-9,]+)/)?.[1]?.replace(/,/g, "") > priceLimit))).forEach(v => { gmDataList_remove(v, "gmHideByyodoComma"); if (!gmDataList_includesPartial(v, 'gmHideBy')) $(v).show(999) })
            }, 999))
            return false
          }
        },
        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() { // a::
      GF.sortTime = (GF?.sortTime || 1) + 1;
      if (SITE.sortData && location.href.match(SITE.sortUrl)) SITE.sortData.forEach(e => {
        sortEle(e.sortPpr, e.sortElement, "useppr")
        popup3("");
        popup3(`a:量単価が安い順に並べ替え(優先グループ:${GF?.sortTime%2})`, 8)
      });
      SITE.sortData.reverse()
      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);
        if ((lh('https://www.kohnan-eshop.com/shop/g/') || lh('https://www.komeri.com/disp/') || lh(/^https:\/\/www\.amazon\.co\.jp\/.*dp\//) || lh("https://jp.iherb.com/pr/"))) {
          elegeta('.ppr:not(div.pdTopContainer .ppr),.ppr2:not(div.pdTopContainer .ppr2)').forEach(e => e.classList.add("pprcccopy"))
        }
        if (lh("https://www.yodobashi.com/product/")) {
          elegeta('div.pdTopContainer .ppr,div.pdTopContainer .ppr2').forEach(e => e.classList.add("pprcccopy"))
        }
        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);

        if (SITE.close) {
          var parentEle = titleEle.closest(SITE.close())
          debugEle(parentEle, rndcolor);
        } else {
          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);
        if (SITE.hide) {
          SITE.hide(title, isorder, isproduct, issearch, parentEle, price, iscate, cppLimit, point, titleEle);
          if ((lh('https://www.kohnan-eshop.com/shop/g/') || lh('https://www.komeri.com/disp/') || lh(/^https:\/\/www\.amazon\.co\.jp\/.*dp\//) || lh("https://jp.iherb.com/pr/"))) {
            elegeta('.ppr:not(div.pdTopContainer .ppr),.ppr2:not(div.pdTopContainer .ppr2)').forEach(e => e.classList.add("pprcccopy"))
          }
          if (lh("https://www.yodobashi.com/product/")) {
            elegeta('div.pdTopContainer .ppr,div.pdTopContainer .ppr2').forEach(e => e.classList.add("pprcccopy"))
          }
        }
      }
    }
  }

  function elegeta(xpath, node = document) {
    if (!xpath || !node) return [];
    let xpath2 = xpath.replace(/:inscreen|:visible|:text\*=[^:]*/g, "") // text*=~中で:は使えない
    let array = []
    try {
      if (!/^\.?\//.test(xpath)) {
        array = [...node.querySelectorAll(xpath2)]
      } else {
        var snap = document.evaluate("." + xpath2, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
        let l = snap.snapshotLength
        for (var i = 0; i < l; i++) array[i] = snap.snapshotItem(i)
      }
      if (/:visible/.test(xpath)) array = array.filter(e => e.offsetHeight)
      if (/:inscreen/.test(xpath)) array = array.filter(e => { var eler = e.getBoundingClientRect(); return (eler.bottom >= 0 && eler.right >= 0 && eler.left <= document.documentElement.clientWidth && eler.top <= document.documentElement.clientHeight) }) // 画面内に1ピクセルでも入っている
      if (/:text\*=./.test(xpath)) { let text = xpath.replace(/^.*:text\*=([^:]*)$/, "$1"); if (text) array = array.filter(e => new RegExp(text).test(e?.textContent)) }
    } catch (e) { return []; }
    return array
  }

  function eleget0(xpath, node = document) {
    if (!xpath || !node) return null;
    if (/:inscreen|:visible|:text\*=/.test(xpath)) return elegeta(xpath, node)?.shift();
    if (!/^\.?\//.test(xpath)) return node.querySelector(xpath);
    try {
      var ele = document.evaluate("." + xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
      return ele.snapshotLength > 0 ? ele.snapshotItem(0) : null;
    } catch (e) { alert(e + "\n" + xpath + "\n" + JSON.stringify(node)); return null; }
  }

  function dc(str, force = 0) {
    if (debug >= 1 || force) popup3(str, 0, 31000, "top");
    return str;
  }


  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) { ele.style.opacity = "0.5"; } else ele.remove();
    if (debug2 && ele) {
      ele.dataset.hidden = "1";
      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", clickcb = () => {}) {
    if (text === "") { $('.amaqpuall').remove(); return }
    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, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/`/g, '&#x60;').replace(/</g, "&lt;").replace(/>/g, "&gt;").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 amaqpuall amaqpu3${alignY} pu3line${i}s" style=" max-width:33%;font-family:sans-serif; position: fixed; right:0em; ${ alignY }:${maey + i }em; 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>`).click(clickcb).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((function(id) {
      return function() {
        var e = eleget0('//span[@id="amaqpu3' + id + '"]');
        e && e?.remove();
      }
    })(id), 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フラグ不可
  function lo(re) { let tmp = location.origin.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可

  function domsort(containerEle, domEles, func, prepend = 0) { // container:domsの入っている大枠、省略時はdomsの1つ親 doms:並べ替える要素たち prepend:0:containerの最後に付ける昇順 1:containerの最後に付ける降順
    if (containerEle === "") containerEle = domEles[0]?.parentNode
    if (!containerEle || !domEles.length) return
    if (Array.isArray(containerEle)) containerEle = containerEle.shift()
    let col = new Intl.Collator("ja", { numeric: true, sensitivity: 'base' }) //.compare
    let doms2 = prepend ?
      (domEles.map(function(v, i) { return { dom: v, value: func(v, i) } }).sort(function(a, b) { return (!isNaN(b.value) && !isNaN(a.value) ? (a.value - b.value) : b.value == a.value ? 0 : (col.compare(a.value, b.value))) })) :
      (domEles.map(function(v, i) { return { dom: v, value: func(v, i) } }).sort(function(a, b) { return (!isNaN(b.value) && !isNaN(a.value) ? (b.value - a.value) : b.value == a.value ? 0 : (col.compare(a.value, b.value) * -1)) }))
    doms2.forEach(function(v) { containerEle.appendChild(v.dom); })
  }

  function sortdom(doms, func, prepend = 0) { // doms:並べ替える要素たち prepend:0:昇順 1:降順
    let position = doms[0]?.previousElementSibling
    let container = doms[0]?.parentNode
    if (!container || !doms.length) return
    let col = new Intl.Collator("ja", { numeric: true, sensitivity: 'base' })
    let fragment = new DocumentFragment();
    doms.map((v, i) => { return { dom: v, value: func(v, i) } }).sort((a, b) => (prepend == 0 ?
      (!isNaN(b.value) && !isNaN(b.value) ? a.value == b.value ? 0 : (a.value - b.value) : a.value == b.value ? 0 : (col.compare(a.value, b.value))) :
      (!isNaN(a.value) && !isNaN(b.value) ? a.value == b.value ? 0 : (b.value - a.value) : a.value == b.value ? 0 : (col.compare(b.value, a.value)))
    )).forEach(v => fragment?.append(v.dom))
    position ? position.parentNode.insertBefore(fragment, position.nextSibling) : container.prepend(fragment)
  }

  function en(v, no = 0) {
    return parseFloat(v?.textContent?.replace(/\,/gm, "")?.match(/[0-9,]+/gm)?.[no]?.toNum());
  }

  function engine2() { // e2::
    // 上が優先
    const SITEINFO = [{
      is: () => lh('//page.auctions.yahoo.co.jp/jp/auction/'),
      title: n => eleget0('h1.ProductTitle__text', n),
      box: n => elegeta('div.l-containerInner'),
      price2: n => (en(eleget0('span.Price__tax', n), 0) || en(eleget0('dd.Price__value', n), 0)) + (en(eleget0('span.Price__postageValue', n), 0) || 0),
      pprTagOption: `style="font-size:90%;" `,
      cccopy: 1,
    }, {
      is: () => lh('//auctions.yahoo.co.jp/search/search'),
      title: n => eleget0('a.Product__titleLink', n),
      box: n => elegeta('li.Product'),
      price2: n => en(eleget0('span.Product__priceValue.u-textRed', n), 0) + (en(eleget0('p.Product__postage', n), 0) || 0),
      //price: n => eleget0('span.Product__priceValue.u-textRed', n),
      pprPlace: n => n,
      pprTagOption: `style="font-size:90%;" `,
    }, {
      is: () => lh("https://www.kohnan-eshop.com/shop/g/"),
      box: n => elegeta(`div.pane-contents`, n),
      title: n => eleget0(`h1.block-goods-name.js-enhanced-ecommerce-goods-name`, n),
      price: n => eleget0(`//div[@class="block-cartbox-section--price-price"]`, n),
      pprPlace: n => n,
      pprTagOption: `style="font-size:80%;" `,
      delay: 2222,
      cccopy: 1,
    }, {
      is: () => lh("https://www.kohnan-eshop.com/shop/goods/"),
      box: n => elegeta(`.block-thumbnail-t li`, n),
      title: n => eleget0(`.block-thumbnail-t--goods-name a`, n),
      price: n => eleget0(`.block-thumbnail-t--price-items div`, n),
      pprPlace: n => n,
      pprTagOption: `style="font-size:80%;" `,
      dni: 555,
      func: () => addstyle.add(`div.block-thumbnail-t--goods-name{height:auto !important;}`),
    }, {
      is: () => lh("https://www.topvalu.net/items/list/|https://www.topvalu.net/search/"),
      box: n => elegeta(`article.product__item`, n),
      title: n => eleget0(`div.product__item__spec`, n),
      price: n => eleget0(`div.product__item__taxin`, n),
      pprPlace: n => n,
      pprTagOption: `style="font-size:95%;" `,
      dni: 555,
      func: () => setInterval(() => eleget0('div.product__button[data-products-role="refill"]:inscreen:visible')?.click(), 2000),
    }, {
      is: () => lh("https://www.topvalu.net/items/detail/"),
      box: n => elegeta(`div.main__inner.item-detail`, n),
      title: n => eleget0(`dd.item-detail__specs__value`, n),
      price: n => eleget0(`dd.item-detail__specs__value.item-detail__specs__value--price`, n),
      pprTagOption: `style="font-size:110%;" `,
      cccopy: 1,
    }, {
      is: () => lh("https://www1.pcdepot.co.jp/products/detail/"),
      box: n => elegeta(`div.m-detail_inner`, n),
      title: n => eleget0(`//div[@class="m-detail_title_inner"]/h1/span`, n),
      price: n => eleget0(`span.leading`, n),
      cccopy: 1,
    }, {
      is: () => lh("https://www1.pcdepot.co.jp/products/list"),
      box: n => elegeta(`//div[@class="m-commodity_inner"]/ul/li`, n),
      title: n => eleget0(`div.m-commodity_title`, n),
      price: n => eleget0(`div.m-commodity_price.text-nowrap`, n),
      cccopy: 1,
    }, {
      is: () => lh("https://sundrug-online.com/products/"),
      box: n => elegeta(`//div[@class="card__section"]`, n),
      title: n => eleget0(`h1.product-meta__title.heading.h1`, n),
      price: n => eleget0(`//div/div[@class="price-list"]/span[@class="price"]`, n),
      cccopy: 1,
    }, {
      is: () => lh("https://sundrug-online.com/search"),
      box: n => elegeta(`//div[@class="product-item product-item--vertical  1/3--tablet-and-up 1/4--desk"]`, n),
      title: n => eleget0(`a.product-item__title.text--strong.link`, n),
      price: n => eleget0(`span.price`, n),
      func: () => setInterval(run, 999, SITE),
      cccopy: 1,
    }, {
      is: () => lh("https://sundrug-online.com/collections/"),
      box: n => elegeta(`//div[@class="product-item product-item--vertical  1/3--tablet 1/4--lap-and-up"]|//div[@class="product-item product-item--vertical  1/3--tablet-and-up 1/4--desk"]`, n),
      title: n => eleget0(`a.product-item__title.text--strong.link`, n),
      price: n => eleget0(`span.price`, n),
      func: () => setInterval(run, 999, SITE),
      cccopy: 1,
    }, {
      is: () => lh("https://nttxstore.jp/_II_"),
      box: n => elegeta(`//div[@id="incontents"]`, n),
      title: n => eleget0(`div#incontents>h1`, n),
      price: n => eleget0(`dd.price>span`, n),
      cccopy: 1,
    }, {
      is: () => lo("https://nttxstore.jp"),
      box: n => elegeta(`div#schphoto>ul>li`, n),
      title: n => eleget0(`//div[@class="name"]/a`, n),
      price: n => eleget0(`//div[@class="price"]`, n),
    }, {
      is: () => lo("search.rakuten.co.jp"),
      box: n => elegeta(`div.dui-card.searchresultitem`, n),
      title: n => eleget0(`a[class*="title-link--"]`, n),
      price: n => eleget0(`div[class*="price--"]`, n),
    }]
    /*
     price2:node=>number, // nodeから価格(数値)を返す
    */

    let SITE = SITEINFO.find(v => v.is())
    if (!SITE) return "not target";

    let addstyle = {
      added: [],
      add: function(str) {
        if (this.added.some(v => v[1] === str)) return;
        var S = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" //      var S="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
        var d = Date.now()
        var uid = Array.from(Array(12)).map(() => S[Math.floor((d + Math.random() * S.length) % S.length)]).join('')
        end(document.head, `<style id="${uid}">${str}</style>`);
        this.added.push([uid, str]);
        return uid;
      },
      remove: function(str) { // str:登録したCSSでもaddでreturnしたuidでも良い
        let uid = this.added.find(v => v[1] === str || v[0] === str)?.[0]
        if (uid) {
          eleget0(`#${uid}`)?.remove()
          this.added = this.added.filter(v => v[0] !== uid)
        }
      }
    }

    String.prototype.match0 = function(re) { let tmp = this.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可
    String.prototype.toNum = function() { return this.replace(/\,/gm, "").match0(/[0-9\.]+/gm, "") }
    GM_addStyle(`.ppr,.ppr2 {all:initial;position:relative;z-index:999; cursor:pointer; display:inline-block; font-weight:bold; 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;}`)

    if (typeof $ === "undefined") { window.addEventListener('DOMContentLoaded', function() { run0(); return; }) } else { run0(); }

    function run0() {
      setTimeout(() => run(SITE, document.body), SITE?.delay || 0)
      document.body.addEventListener('AutoPagerize_DOMNodeInserted', function(evt) { run(SITE, evt.target); }, false);
      if (SITE.func) SITE.func()
      if (SITE?.dni) document.body.addEventListener('DOMNodeInserted', function(evt) {
        clearTimeout(GF.dniId) //}
        GF.dniId = setTimeout(() => run(SITE), SITE?.dni || 999)
      }, false);

      var mousex = 0;
      var mousey = 0;
      document.addEventListener("mousemove", function(e) {
        mousex = e.clientX;
        mousey = e.clientY;
        hovertimer = 0;
      }, false);

      // キーボード
      var keyFunc = [{
        key: "a", // a::
        func: ele => {
          sortdom(SITE.box(), e => eleget0('.ppr', e)?.dataset?.tankafull?.toNum() || Number.MAX_SAFE_INTEGER, 0);
          //sortdom(SITE.box().filter(e => eleget0('.ppr', e)), e => eleget0('.ppr', e)?.dataset?.tankafull?.toNum(), 0);
          popup3(`a:両単価が安い順に並べ替え`, 8, 5000, "bottom");
        }
      }]
      var keyListen = function(e) {
        if (!GF?.use) return;
        if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.getAttribute('contenteditable') === 'true') return;
        var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key;
        var ele = document.elementFromPoint(mousex, mousey);
        var sel = (window.getSelection) ? window.getSelection().toString().trim() : ""
        keyFunc.forEach(v => { if (v.key === key) { v.func(ele) } })
      }
      document.addEventListener('keydown', keyListen, false)
      document.addEventListener('contextmenu', e => {
        if (!GF?.use) return;
        if (e.target.matches(".ppr,.ppr2")) {
          keyFunc.find(v => v.key == "a").func();
          e.preventDefault();
          return false;
        }
      }, false)
      return;
    }

    function run(SITE, node = document.body) {
      SITE.box(node).filter(e => !e.dataset.pprdone).forEach(boxele => {
        boxele.dataset.pprdone = 1
        let priceele = SITE?.price?.(boxele)
        let price = SITE?.price2?.(boxele) || priceele?.textContent?.toNum()
        let titleele = SITE.title(boxele)
        if (price && titleele) {
          //let rc=makeRndColor();
          //[priceele,titleele,boxele].forEach(e=>debugEle(e,rc)) //

          var ryoua = titleele?.textContent?.replace(/[A-Za-z0-9.,]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 65248) })?.replace(/\,/gm, "").match(/\D?([0-9\.]+)\s?(ページ|mg|g|ml|mL|枚|粒|錠|包|杯|本|回分|回用|個|袋|ml|GB|ペア|組|日分|ヶ入|組入|ポート|色|日分|ヶ入|食|巻|入|セット|缶|函)|([0-9\.]+)\s?(L|kg|㎏|Kg|kg|キロ|TB)/); // ntt-x
          let tankaa = []
          if (ryoua?.[1] && ryoua?.[2]) tankaa.push({ value: ryoua[1].toNum(), unitname: ryoua[2] })
          //          if (ryoua?.[3] && ryoua?.[4]) tankaa.push({ value: ryoua[3], valueActual: ryoua[3]?.toNum()*1000, unitname: ryoua[4] })
          if (ryoua?.[3] && ryoua?.[4]) tankaa.push({ value: ryoua[3].toNum() * (ryoua[4] == "TB" ? 1024 : 1000), unitname: ryoua[4].replace(/^L$/, "ml").replace(/^kg$|^キロ$/i, "g").replace(/^TB$/, "GB") }) // 1000倍の単位だったら1/1000の単位に変換
          tankaa.forEach(i => {
            //            let tanka = Math.round((priceele.textContent.toNum() / i.value.toNum()) * 100) / 100
            let tanka = Math.round((price / i.value) * 100) / 100
            //            let tankaFull = (priceele.textContent.toNum() / i.value.toNum())
            //            let tankaFull = (priceele.textContent.toNum() / (i?.valueActual||i.value.toNum() ) )
            let tankaFull = (price / (i?.valueActual || i.value))
            //            after(SITE?.pprPlace?.(titleele) || titleele.parentNode, ` <span class="pprcover"><span class="ppr${SITE?.cccopy?" pprcccopy":""}" ${SITE?.pprTagOption||""} data-tankafull="${tankaFull}" title="¥${priceele?.textContent?.toNum()}/${i.value.toNum()}${i.unitname}=¥${tankaFull}/${i.unitname}">¥${tanka}/${i.unitname}</span></span>`)
            after(SITE?.pprPlace?.(titleele) || titleele.parentNode, ` <span class="pprcover"><span class="ppr${SITE?.cccopy?" pprcccopy":""}" ${SITE?.pprTagOption||""} data-tankafull="${tankaFull}" title="¥${price}/${i.value}${i.unitname}=¥${tankaFull}/${i.unitname}">¥${tanka}/${i.unitname}</span></span>`)
            GF.use = 1
          })
        }
      })
    }

    function elegeta(xpath, node = document) {
      if (!xpath || !node) return [];
      let xpath2 = xpath.replace(/:inscreen|:visible|:text\*=[^:]*/g, "") // text*=~中で:は使えない
      let array = []
      try {
        if (!/^\.?\//.test(xpath)) {
          array = [...node.querySelectorAll(xpath2)]
        } else {
          var snap = document.evaluate("." + xpath2, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
          let l = snap.snapshotLength
          for (var i = 0; i < l; i++) array[i] = snap.snapshotItem(i)
        }
        if (/:visible/.test(xpath)) array = array.filter(e => e.offsetHeight)
        if (/:inscreen/.test(xpath)) array = array.filter(e => { var eler = e.getBoundingClientRect(); return (eler.bottom >= 0 && eler.right >= 0 && eler.left <= document.documentElement.clientWidth && eler.top <= document.documentElement.clientHeight) }) // 画面内に1ピクセルでも入っている
        if (/:text\*=./.test(xpath)) { let text = xpath.replace(/^.*:text\*=([^:]*)$/, "$1"); if (text) array = array.filter(e => new RegExp(text).test(e?.textContent)) }
      } catch (e) { return []; }
      return array
    }

    function eleget0(xpath, node = document) {
      if (!xpath || !node) return null;
      if (/:inscreen|:visible|:text\*=/.test(xpath)) return elegeta(xpath, node)?.shift();
      if (!/^\.?\//.test(xpath)) return node.querySelector(xpath);
      try {
        var ele = document.evaluate("." + xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        return ele.snapshotLength > 0 ? ele.snapshotItem(0) : null;
      } catch (e) { alert(e + "\n" + xpath + "\n" + JSON.stringify(node)); return null; }
    }

    function dc(str, force = 0) {
      if (debug >= 1 || force) popup3(str, 0, 31000, "top");
      return str;
    }


    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) { ele.style.opacity = "0.5"; } else ele.remove();
      if (debug2 && ele) {
        ele.dataset.hidden = "1";
        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", clickcb = () => {}) {
      if (text === "") { $('.amaqpuall').remove(); return }
      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, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/`/g, '&#x60;').replace(/</g, "&lt;").replace(/>/g, "&gt;").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 amaqpuall amaqpu3${alignY} pu3line${i}s" style=" max-width:33%;font-family:sans-serif; position: fixed; right:0em; ${ alignY }:${maey + i }em; 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>`).click(clickcb).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((function(id) {
        return function() {
          var e = eleget0('//span[@id="amaqpu3' + id + '"]');
          e && e?.remove();
        }
      })(id), 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 sortdom(doms, func, prepend = 0) { // doms:並べ替える要素たち func(e):要素eの順位を決める数値か文字列をreturnする関数 prepend:0:昇順 1:降順
      let position = doms[0]?.previousElementSibling
      let container = doms[0]?.parentNode
      if (!container || !doms.length) return
      let col = new Intl.Collator("ja", { numeric: true, sensitivity: 'base' })
      let fragment = new DocumentFragment();
      doms.map((v, i) => { return { dom: v, value: func(v, i) } }).sort((a, b) => (prepend == 0 ?
        (!isNaN(b.value) && !isNaN(b.value) ? a.value == b.value ? 0 : (a.value - b.value) : a.value == b.value ? 0 : (col.compare(a.value, b.value))) :
        (!isNaN(a.value) && !isNaN(b.value) ? a.value == b.value ? 0 : (b.value - a.value) : a.value == b.value ? 0 : (col.compare(b.value, a.value)))
      )).forEach(v => fragment?.append(v.dom))
      position ? position.parentNode.insertBefore(fragment, position.nextSibling) : container.prepend(fragment)
    }

    function before(e, html) { e?.insertAdjacentHTML('beforebegin', html); return e?.previousElementSibling; }

    function begin(e, html) { e?.insertAdjacentHTML('afterbegin', html); return e?.firstChild; }

    function end(e, html) { e?.insertAdjacentHTML('beforeend', html); return e?.lastChild; }

    function after(e, html) { e?.insertAdjacentHTML('afterend', html); return e?.nextElementSibling; }

    function ctLong(callback, name = "test", time = 10) { console.time(name); for (let i = time; i--;) { callback() } console.timeEnd(name) } // 速度測定(もともと長くかかるもの)
    function ct(callback, name = "test", time = 10) { let i = 0; let st = Date.now(); while (Date.now() - st < 1000) { i++, callback() } console.log(`${name} ${i} / 1sec`) } // 速度測定(一瞬で終わるもの)
    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フラグ不可
    function lo(re) { let tmp = location.origin.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可
    function ld(re) { let tmp = location.hostname.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可
    function JS(v) { try { return JSON.stringify(v) } catch { return null } }

    function JP(v) { try { return JSON.parse(v) } catch { return null } }

    function e2sel(ele) { return `${ele.tagName?.toLowerCase()}${ele.id?"#"+ele.id:""}${ele.className?"."+ele.className.replace(/\s/g,"."):""}` }

    function han(str) { return str?.replace(/[A-Za-z0-9]/g, function(s) { return String.fromCharCode(s.charCodeAt(0) - 65248) }) || "" }

    function sani(s) { return s?.replace(/&/g, "&amp;")?.replace(/"/g, "&quot;")?.replace(/'/g, "&#39;")?.replace(/`/g, '&#x60;')?.replace(/</g, "&lt;")?.replace(/>/g, "&gt;") || "" }

    function isValidRE(str) {
      try { new RegExp(str) } catch (e) { return false }
      return true
    }

  }

  function lo(re) { let tmp = location.origin.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可
  function ld(re) { let tmp = location.hostname.match(re); if (!tmp) { return null } else if (tmp.length > 1) { return tmp[1] } else return tmp[0] } // gフラグ不可
  // cssセレクタのみ使え、追加されたノードそのものと子孫の両方に対応。中速
  function moq(targetCSSSelector, func, observeNode = document) {
    func([...observeNode.querySelectorAll(targetCSSSelector)])
    new MutationObserver((m) => {
      let eles = [...m.filter(v => v.addedNodes).map(v => [...v.addedNodes]).filter(v => v.length)].flat().filter(v => v.nodeType === 1)
      let hits = eles.filter(v => v?.matches(targetCSSSelector)).concat(eles?.map(v => [...v?.querySelectorAll(targetCSSSelector)])?.flat())
      if (hits.length) func(hits)
    })?.observe(observeNode || document.body, { attributes: false, childList: true, subtree: true });
  }

  // element.dataset.gmDataListプロパティにclassList.add/removeのような命令セット
  function gmDataList_add(ele, name) {
    let data = ele?.dataset?.gmDataList?.split(" ") || []
    if (!data.includes(name)) {
      data.push(name);
      ele.dataset.gmDataList = data.join(" ")
    }
  }

  function gmDataList_remove(ele, name) {
    let data = ele?.dataset?.gmDataList?.split(" ") || []
    if (data.includes(name)) {
      data = data.filter(v => v !== name)
      if (data.length) ele.dataset.gmDataList = data.join(" ");
      else delete ele.dataset.gmDataList;
    }
  }

  function gmDataList_includesPartial(ele, name) { // *[class*="name"]のような部分一致
    let data = ele?.dataset?.gmDataList?.split(" ") || []
    return data.find(v => v.includes(name))
  }
})();