diff --git a/ab-tag-chips.user.js b/ab-tag-chips.user.js new file mode 100644 index 0000000..3e3304a --- /dev/null +++ b/ab-tag-chips.user.js @@ -0,0 +1,112 @@ +// ==UserScript== +// @name AB Tag Chips +// @version 1.0 +// @description convert tags to chips for quicker selection and improve selecting ux +// @author Marv, metonym +// @match https://animebytes.tv/upload.php +// @icon https://animebytes.tv/favicon.ico +// @grant GM_addStyle +// ==/UserScript== + +// yoinked from https://github.com/MarvNC/AB-enhancements/raw/master/ab-better-upload-page.user.js +// with some improvements + +const EXCLUDE_OPTIONS = ['', '---']; + +const ADD_CSS = /* css */ ` +/* Container styles */ +.chip-container { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 8px; +} + +/* Chip styles */ +.chip { + background-color: white; + border-radius: 12px; + padding: 6px 12px; + font-size: 12px; + color: #555; + cursor: pointer; + transition: background-color 0.3s ease; + border: 1px solid #ccc; + text-align: center; + font-weight: 600; +} + +/* Hover effect */ +.chip:hover { + background-color: #eeeeee; +} + +/* Selected chip */ +.chip.selected { + background-color: #555; + color: white; +} +`; + +let selectedTags = []; + +(function() { + 'use strict'; + + GM_addStyle(ADD_CSS); + + convertTagSelectsToInputChips(); +})(); + +/** + * converts the tag selects to input chips by hiding the select and adding a chip for each option that is selected + * also improves the UX when selecting and unselecting a tag so that the input box updates appropriately + */ +function convertTagSelectsToInputChips() { + const selects = [...document.querySelectorAll("select[id^='genre_tags_']")]; + const inputs = [...document.querySelectorAll("input[id^='tags_']")]; + for (const select of selects) { + select.style.display = 'none'; + + // could probably do this better but it works /shrug + let input = null; + for (const inp of inputs) { + if (select.id.endsWith(inp.id)) { + input = inp; + break; + } + } + + const parent = select.parentElement; + const chipContainer = document.createElement('div'); + chipContainer.className = 'chip-container'; + parent.prepend(chipContainer); + + const options = [...select.options]; + for (const option of options) { + if (EXCLUDE_OPTIONS.includes(option.textContent)) { + continue; + } + const chip = document.createElement('div'); + chip.className = 'chip'; + chip.textContent = option.textContent; + + chip.addEventListener('click', () => { + let isSelected = selectedTags.includes(option.textContent); + if (!isSelected) { + selectedTags.push(option.textContent); + } else { + let i = selectedTags.indexOf(option.textContent); + selectedTags.splice(i, 1); + } + + chip.classList.toggle('selected', !isSelected); + + selectedTags.sort() + input.value = selectedTags.join(", "); + }); + + chipContainer.appendChild(chip); + } + } +} \ No newline at end of file