Return +/- buttons to Danbooru
// ==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);
}
})();