Amazon_Keepa_Sakura_Button

Add links to Keepa and Sakura Checker to the Amazon.co.jp product screen.

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

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

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

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

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

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

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

Advertisement:

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

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

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

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

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

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

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

Advertisement:

// ==UserScript==
// @name            Amazon_Keepa_Sakura_Button
// @name:ja         Amazonの商品画面に価格履歴とサクラチェックのボタンを追加
// @namespace       https://greasyfork.org/users/1324207
// @match           https://www.amazon.co.jp/dp/*
// @match           https://www.amazon.co.jp/*/dp/*
// @match           https://www.amazon.co.jp/gp/product/*
// @match           https://www.amazon.co.jp/exec/obidos/ASIN/*
// @match           https://www.amazon.co.jp/o/ASIN/*
// @match           https://www.amazon.co.jp/gp/aw/d/*
// @version         1.5.0
// @author          Lark8037
// @description     Add links to Keepa and Sakura Checker to the Amazon.co.jp product screen.
// @description:ja  Amazonの商品画面にKeepaとサクラチェッカーへのリンクを追加します。
// @run-at          document-idle
// @license         MIT
// @noframes
// @icon            https://www.amazon.co.jp/favicon.ico
// ==/UserScript==

((d, l, h, w) => {
    'use strict';

    const CID = 'checker-links',
        SID = 'checker-style',
        DA = 'data-asin',
        SEC = 'div.a-section',
        K = 'https://keepa.com/#!product/5-',
        S = 'https://sakura-checker.jp/search/',
        T = '" target="_blank" rel="noopener noreferrer">',
        RE = /[A-Z0-9]{10}/i,
        QE = /(?:^|[?&])asin=([A-Z0-9]{10})(?=&|$)/i;

    let cur = '',
        lastForm = '',
        lastUrl = '',
        timer = 0,
        gen = 0;

    const norm = v => {
        v = v && RE.exec(v);
        return v ? v[0].toUpperCase() : '';
    };

    function formASIN() {
        let e = d.getElementById('ASIN'),
            n,
            i,
            v;

        if ((v = e && norm(e.value))) return v;

        n = d.getElementsByName('ASIN');
        for (i = 0; i < n.length; i++) {
            if ((v = norm(n[i].value))) return v;
        }

        n = d.getElementsByName('ASIN.0');
        for (i = 0; i < n.length; i++) {
            if ((v = norm(n[i].value))) return v;
        }

        return '';
    }

    function urlASIN() {
        const m = QE.exec(l.search);
        return m ? m[1].toUpperCase() : norm(l.pathname);
    }

    function getASIN() {
        const f = formASIN(),
            u = urlASIN(),
            r = cur
                ? f && f !== lastForm
                    ? f
                    : u && u !== lastUrl
                        ? u
                        : f === cur || u === cur
                            ? cur
                            : f || u
                : f || u;

        lastForm = f;
        lastUrl = u;

        return r || '';
    }

    function style() {
        d.getElementById(SID) || (d.head || d.documentElement).insertAdjacentHTML(
            'beforeend',
            `<style id="${SID}">
#checker-links{contain:content}
#checker-links>a,.checker>a{display:block;border:0;height:4ex;line-height:4ex;margin-bottom:1.2ex;width:100%;text-align:center;color:#000;border-radius:10em;text-decoration:none;font-size:1em}
#checker-links>.price-history-link,.checker>.price-history-link{background:deepskyblue}
#checker-links>.price-history-link:hover,.checker>.price-history-link:hover{background:dodgerblue}
#checker-links>.sakura-checker-link,.checker>.sakura-checker-link{background:deeppink}
#checker-links>.sakura-checker-link:hover,.checker>.sakura-checker-link:hover{background:crimson}
@media(max-width:768px){#checker-links>a,.checker>a{height:5.5ex;line-height:5.5ex}}
</style>`
        );
    }

    const links = a =>
        '<a class="price-history-link" href="' + K + a + T + '価格履歴</a>' +
        '<a class="sakura-checker-link" href="' + S + a + '/' + T + 'サクラチェック</a>';

    function target() {
        return d.getElementById('buyNow') ||
            d.getElementById('add-to-cart-button') ||
            d.getElementById('buybox')?.getElementsByClassName('a-button-stack')[0] ||
            d.getElementById('add-to-cart-button-ubb') ||
            d.getElementById('buybox-see-all-buying-choices') ||
            d.getElementById('buybox-see-all-buying-choices-announce') ||
            d.getElementById('rcx-subscribe-submit-button-announce') ||
            d.getElementById('dealsAccordionRow') ||
            d.getElementById('outOfStock');
    }

    function setLinks(c, a) {
        const x = c.children;

        c.setAttribute(DA, a);

        if (x.length > 1) {
            x[0].href = K + a;
            x[1].href = S + a + '/';
        } else {
            c.innerHTML = links(a);
        }
    }

    function place(c) {
        const e = target(),
            p = e?.closest?.(SEC) || e?.parentNode;

        if (p?.parentNode && c.previousElementSibling !== p) {
            p.parentNode.insertBefore(c, p.nextSibling);
        }

        return !!p;
    }

    function draw(a) {
        const c = d.getElementById(CID);
        let e,
            p;

        if (c) {
            if (c.getAttribute(DA) !== a) {
                setLinks(c, a);
                place(c);
            }

            cur = a;
            return 1;
        }

        if (!(e = target()) || !(p = e.closest?.(SEC) || e.parentNode)) return 0;

        style();

        p.insertAdjacentHTML(
            'afterend',
            '<div id="' + CID + '" class="checker" ' + DA + '="' + a + '">' + links(a) + '</div>'
        );

        cur = a;
        return 1;
    }

    function sync() {
        const a = getASIN();
        return a ? draw(a) : 0;
    }

    function pulse() {
        let i = 0;
        const g = ++gen,
            f = () => {
                if (g !== gen) return;

                sync();

                timer = ++i < 7
                    ? w.setTimeout(f, i < 2 ? 64 : i < 3 ? 160 : i < 4 ? 400 : i < 5 ? 900 : 1800)
                    : 0;
            };

        if (timer) w.clearTimeout(timer);
        timer = w.setTimeout(f, 0);
    }

    function boot(n, t) {
        if (!sync() && n) {
            w.setTimeout(() => {
                boot(n - 1, t < 1024 ? t << 1 : t);
            }, t);
        }
    }

    function hook(name) {
        const fn = h[name];

        if (typeof fn !== 'function') return;

        h[name] = function () {
            const r = fn.apply(this, arguments);
            pulse();
            return r;
        };
    }

    hook('pushState');
    hook('replaceState');

    w.addEventListener('popstate', pulse, true);
    d.addEventListener('click', pulse, true);
    d.addEventListener('change', pulse, true);

    boot(16, 32);
})(document, location, history, window);