Melonbooks: wishlist: better remove button

Replace wishlist remove button. Compatible with AutoPagerize.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Melonbooks: wishlist: better remove button
// @namespace    http://darkfader.net/
// @version      0.1
// @description  Replace wishlist remove button. Compatible with AutoPagerize.
// @author       Rafael Vuijk
// @match        https://www.melonbooks.co.jp/mypage/favorite.php
// @grant        none
// ==/UserScript==

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

HTMLElement.prototype.remove = function() { this.parentNode.removeChild(this); return this; }

String.prototype.rsplit = function(sep, maxsplit) {
    var split = this.split(sep);
    return maxsplit ? [ split.slice(0, -maxsplit).join(sep) ].concat(split.slice(-maxsplit)) : split;
}

let transactionid = null;

// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
async function delete_favorite(product_id) {
    let formData = new FormData();
    formData.append('mode', 'delete_favorite');
    formData.append('product_id', product_id);
    formData.append('transactionid', transactionid);

    const response = await fetch("https://www.melonbooks.co.jp/mypage/favorite.php?", {
        method: 'POST',
        body: formData,
    });
    return await response;
}

function onReady() {

    // get CSRF token
    transactionid = document.body.querySelector('input[name="transactionid"]').getAttribute('value');

    // var xpath = "//div[contains(@class, 'item')]";
    const xpath = "//div[@class='wishlist']//tr";

    function process(node) {
        let results = document.evaluate(xpath, node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

        for (let i = 0; i < results.snapshotLength; i++) {
            let e = results.snapshotItem(i);

            if (e.hasAttribute('proc')) {    // skip already processed elements. required?
                continue;
            }
            e.setAttribute('proc', true);

            try {
                // console.log(e);

                let item = e.querySelector('td.item');
                let title = item.querySelector('p.title');
                let action = e.querySelector('td.action');

                // get product id
                let href = title.querySelector('a').getAttribute('href');
                const product_id = href.rsplit('=', 1).slice(-1)[0];

                // remove old button
                action.querySelector('a[onclick*="delete_favorite"]').remove();

                /*
                // uhh.. we don't actually need to create a form...
                var f = document.createElement('form');
                f.setAttribute('target', "_blank");
                f.setAttribute('method', "post");
                f.setAttribute('action', "https://www.melonbooks.co.jp/mypage/favorite.php?");

                let ff = document.createElement('input');
                ff.setAttribute('type', "hidden");
                ff.setAttribute('name', "mode");
                ff.setAttribute('value', "delete_favorite");
                f.appendChild(ff);

                ff = document.createElement('input');
                ff.setAttribute('type', "hidden");
                ff.setAttribute('name', "product_id");
                ff.setAttribute('value', product_id);
                f.appendChild(ff);

                ff = document.createElement('input');
                ff.setAttribute('type', "hidden");
                ff.setAttribute('name', "transactionid");
                ff.setAttribute('value', transactionid);
                f.appendChild(ff);

                // product_class_id: 483710
                // quantity: 1
*/
                let ff = document.createElement('input');
//                ff.setAttribute('type', "submit");
                ff.setAttribute('type', "button");
                ff.setAttribute('value', 'remove from wishlist');
                ff.setAttribute('class', 'input_btn br_5'); // doesn't work

                // anchor had these styles...
                ff.setAttribute('style', "\
                display: block;\
                font-size: 12px;\
                text-indent: 0px;\
                border: 1px solid #a09d9e;\
                background: -webkit-linear-gradient( 90deg, rgb(230,230,230) 0%, rgb(255,255,255) 100%);\
                color: #333333;\
                line-height: 24px;");

                action.appendChild(ff);
                //action.appendChild(f);

                ff.addEventListener("click", () => {
                    console.log('click');
                    delete_favorite(product_id).then(response => {
                        if (response.ok) {
                            console.log('yep');
                            e.remove();
                        }
                    }).catch((error) => {
                        console.error('Error:', error);
                    });
                });

                //f.appendChild(ff);

            } catch (error) {
                console.log(error);
            }
        }
    }

    process(document.body);

    var config = { attributes: false, childList: true, characterData: false, subtree: true };

    (document.body.observer = new MutationObserver(function processMutations(mutations) {
        for (var m of mutations) {
            if (m.type == 'childList') {
                if (m.removedNodes.length > 0) {
                    return;// replaced?????
                }
                // TODO: order table, form, div. take highest order.
                [].forEach.call(m.addedNodes, function(v,i,a) {
//                    console.log("type " + type(v));
                    if (v instanceof HTMLTableElement || v instanceof HTMLFormElement || v instanceof HTMLDivElement || v instanceof HTMLSpanElement) {
                        process(v);
                    }
                });
            }
        }
    })).observe(document.body, config);
}

// start the onReady...
if (document.readyState !== "loading") {
    setTimeout(onReady, 0);
} else {
    document.addEventListener("DOMContentLoaded", onReady);
}