Danbooru tags buttons

Return +/- buttons to Danbooru

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==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);
    }
})();