Danbooru tags buttons

Return +/- buttons to Danbooru

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Danbooru tags buttons
// @namespace    danbooru
// @version      0.5
// @description  Return +/- buttons to Danbooru
// @author       Jallot
// @include      http*://*danbooru.donmai.us/posts*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';
    let currentTags = document.getElementById("tags").value.split(" ").filter(String);

    function addTagToSearch(tag, negative=false){
        var newTags = [...currentTags]
        if (negative){
            tag = "-" + tag;
        }
        newTags.push(tag);
        return newTags.join("+");
    };


    const tagList = document.querySelectorAll('ul li[class*="tag-type-"]');
    for (const tag of tagList) {
        const tagLinks = tag.querySelectorAll("a");
        const tagNameNode = tagLinks[1];
        const tagUrl = new URLSearchParams(tagNameNode.href.split('?')[1]);
        const tagName = tagUrl.get("tags");
        var plusLink = document.createElement('a');
        plusLink.href = '/posts?tags=' + addTagToSearch(tagName);
        plusLink.textContent = '+';
        var minusLink = document.createElement('a');
        minusLink.href = '/posts?tags=' + addTagToSearch(tagName, true);
        minusLink.textContent = '-';
        tagNameNode.parentNode.insertBefore(plusLink, tagNameNode);
        tagNameNode.parentNode.insertBefore(document.createTextNode(" "), tagNameNode);
        tagNameNode.parentNode.insertBefore(minusLink, tagNameNode);
        tagNameNode.parentNode.insertBefore(document.createTextNode(" "), tagNameNode);
    };

    const tagBox = document.getElementById("tag-box");
    if (tagBox) {
        const ageSection = document.createElement("section");
        ageSection.id = "age-filter-box";

        const heading = document.createElement("h2");
        heading.textContent = "Age Filter";
        ageSection.appendChild(heading);

        const customDiv = document.createElement("div");
        customDiv.style.cssText = "display:flex;flex-direction:column;gap:4px;";

        const rangeRow = document.createElement("div");
        rangeRow.style.cssText = "display:flex;align-items:center;gap:4px;";

        const fromLabel = document.createElement("span");
        fromLabel.textContent = "from";

        const fromInput = document.createElement("input");
        fromInput.type = "number";
        fromInput.min = "0";
        fromInput.placeholder = "0";
        fromInput.style.cssText = "width:50px;";

        const toLabel = document.createElement("span");
        toLabel.textContent = "to";

        const toInput = document.createElement("input");
        toInput.type = "number";
        toInput.min = "0";
        toInput.placeholder = "0";
        toInput.style.cssText = "width:50px;";

        rangeRow.appendChild(fromLabel);
        rangeRow.appendChild(fromInput);
        rangeRow.appendChild(toLabel);
        rangeRow.appendChild(toInput);

        const unitSelect = document.createElement("select");
        for (const [val, label] of [["d","days"],["w","weeks"],["mo","months"],["y","years"]]) {
            const opt = document.createElement("option");
            opt.value = val;
            opt.textContent = label;
            unitSelect.appendChild(opt);
        }

        // Restore saved age filter state
        const savedAge = sessionStorage.getItem("age-filter");
        if (savedAge) {
            const m = savedAge.match(/^age:(\d+)(\w+)\.\.(\d+)(\w+)$/);
            if (m) {
                fromInput.value = m[1];
                toInput.value = m[3];
                unitSelect.value = m[2];
            }
        }

        const addBtn = document.createElement("button");
        addBtn.textContent = "Search";
        addBtn.addEventListener("click", function() {
            const from = fromInput.value;
            const to = toInput.value;
            const unit = unitSelect.value;
            if (from === "" || to === "") return;
            const ageTag = "age:" + from + unit + ".." + to + unit;
            sessionStorage.setItem("age-filter", ageTag);
            const tagsWithoutAge = currentTags.filter(t => !t.startsWith("age:"));
            tagsWithoutAge.push(ageTag);
            window.location.href = "/posts?tags=" + tagsWithoutAge.join("+");
        });

        customDiv.appendChild(rangeRow);
        customDiv.appendChild(unitSelect);
        customDiv.appendChild(addBtn);
        ageSection.appendChild(customDiv);

        // Shift buttons — only shown when age filter is active
        if (savedAge) {
            const shiftDiv = document.createElement("div");
            shiftDiv.style.cssText = "display:flex;flex-wrap:wrap;gap:4px;margin-top:4px;";

            function shiftAge(direction) {
                const from = parseInt(fromInput.value);
                const to = parseInt(toInput.value);
                const unit = unitSelect.value;
                if (isNaN(from) || isNaN(to)) return;
                const span = to - from;
                const newFrom = Math.max(0, from + direction * span);
                const newTo = newFrom + span;
                const ageTag = "age:" + newFrom + unit + ".." + newTo + unit;
                sessionStorage.setItem("age-filter", ageTag);
                const tagsWithoutAge = currentTags.filter(t => !t.startsWith("age:"));
                tagsWithoutAge.push(ageTag);
                window.location.href = "/posts?tags=" + tagsWithoutAge.join("+");
            }

            const shiftLabel = document.createElement("span");
            shiftLabel.textContent = "Date shifting";
            shiftLabel.style.cssText = "width:100%;";
            shiftDiv.appendChild(shiftLabel);

            const prevBtn = document.createElement("button");
            prevBtn.textContent = "-1";
            prevBtn.addEventListener("click", () => shiftAge(-1));

            const nextBtn = document.createElement("button");
            nextBtn.textContent = "+1";
            nextBtn.addEventListener("click", () => shiftAge(+1));

            shiftDiv.appendChild(prevBtn);
            shiftDiv.appendChild(nextBtn);
            ageSection.appendChild(shiftDiv);
        }

        tagBox.after(ageSection);
    }
})();