} spanList
* @param {string} code
* @param {HTMLElement} tagList
* @param {boolean} [skip1]
*/
function handleListIndexPress(ev, hotkeyType, spanList, code, tagList, skip1) {
if (isCorrectKeyModifier(ev, hotkeyType)) {
ev.preventDefault()
for (const span of spanList) {
span.style.display = 'inline'
}
const keyIndex = hotkeys.index.keys.indexOf(code)
if (keyIndex !== -1) {
const child = tagList.children[keyIndex + (skip1 ? 1 : 0)];
(child.querySelector('button') || child).click()
}
}
}
tagInput.addEventListener('keydown', /** @param {KeyboardEvent} ev */ev => {
const code = ev.code.replace('Digit', '').replace('Key', '')
if (code === 'Space') {
addCommaToEndAndDrawCurrent()
tagInput.value = tagInput.value.replace(/ $/, '')
return
}
const hasSuggestions = autocompleteDiv.children.length > 0
if (hasSuggestions) { // add suggestion by index
handleListIndexPress(ev, 'index', suggestionIdxSpans, code, autocompleteDiv, true)
} else {
handleListIndexPress(ev, 'favorites', favIdxSpans, code, favsList)
}
handleListIndexPress(ev, 'presets', presetIdxSpans, code, presetsList)
// tab submit shortcut
if (isGroupPage && tagInput.value && !hasSuggestions && !acceptedSuggestion && code === 'Tab')
addTagsButton.click()
acceptedSuggestion = false
})
let originalTagColor
function addTag(tag) {
const groupTags = [...groupTagDivs].map(div => div.children[0])
const existingTag = groupTags.find(t => t.textContent === tag)
if (existingTag) {
originalTagColor ??= window.getComputedStyle(existingTag).getPropertyValue('color')
existingTag.style.color = '#69c364'
setTimeout(() => existingTag.style.color = originalTagColor, 1000)
return
}
if (!tagInput.value) {
tagInput.value = tag
} else {
const tags = tagInput.value.replace(trailingCommaRegex, '').split(TAGSEPERATOR)
if (!tags.includes(tag)) {
tags.push(tag)
}
tagInput.value = tags.join(TAGSEPERATOR)
}
tagInput.focus()
tagInput.setSelectionRange(-1, -1)
addCommaToEndAndDrawCurrent()
drawCurrentTags()
}
// region Favorites
//
//
//
//
function drawFavorites() {
let html = ''
for (const [idx, tag] of getFavorites().entries()) {
html += `
${idx + 1}.
${hotkeys.favorites.keys?.[idx] ?? ''}
`
}
favsList.innerHTML = html
favsList.querySelectorAll('.tag').forEach(el => {
el.addEventListener('click', event => {
event.preventDefault()
const tag = event.target.dataset.tag
if (removalCheckbox.checked) {
removeFavorite(tag).then(() => {
drawFavorites()
})
} else {
addTag(tag)
}
})
})
}
async function removeFavorite(tag) {
let _temp = []
for (const fav of getFavorites()) {
if (fav !== tag) {
_temp.push(fav)
}
}
currentFavoritesDict[currentUploadCategory] = _temp
return GM.setValue('favorites', currentFavoritesDict)
}
document.getElementById('th-add-fav').onclick = async () => {
const currentFavorites = getFavorites()
const tags = parse_text_to_tag_list()
.filter((value, index, array) => !array.some(value => currentFavorites.includes(value)))
currentFavoritesDict[currentUploadCategory] = currentFavorites.concat(...tags)
await GM.setValue('favorites', currentFavoritesDict)
drawFavorites()
}
function getFavorites() {
return currentFavoritesDict[currentUploadCategory] || []
}
//
//
//
//
// endregion
//region Presets
//
//
//
//
function drawPresets() {
let html = ''
for (const [idx, preset] of getPresets().entries()) {
html += `
${idx + 1}.
${hotkeys.presets.keys?.[idx] ?? ''}
`
}
presetsList.innerHTML = html
presetsList.querySelectorAll('.tag').forEach((el) => {
el.addEventListener('click', event => {
event.preventDefault()
const preset = event.target.dataset.preset
if (removalCheckbox.checked) {
removePreset(preset).then(() => {
drawPresets()
})
} else {
for (const tag of parse_text_to_tag_list(preset)) {
addTag(tag)
}
}
})
})
}
function getPresets() {
return currentPresetsDict[currentUploadCategory] || []
}
async function removePreset(preset) {
let _temp = []
for (const pres of getPresets()) {
if (pres !== preset) {
_temp.push(pres)
}
}
currentPresetsDict[currentUploadCategory] = _temp
return GM.setValue('presets', currentPresetsDict)
}
document.getElementById('th-add-preset').onclick = async () => {
const str = parse_text_to_tag_list().join(TAGSEPERATOR)
const currentPresets = getPresets()
if (!currentPresets.includes(str)) {
currentPresetsDict[currentUploadCategory] = currentPresets.concat(str)
await GM.setValue('presets', currentPresetsDict)
drawPresets()
}
}
//
//
//
//
//endregion
/** @returns {string[]} */
function parse_text_to_tag_list(text = tagInput.value) {
let tagList = []
for (let tag of text.replaceAll(' ', '').split(TAGSEPERATOR.trim())) {
tag.trim() && tagList.push(tag)
}
return tagList
}
function addCommaToEndAndDrawCurrent() {
if (tagInput.value && !trailingCommaRegex.test(tagInput.value)) {
tagInput.value += TAGSEPERATOR
}
drawCurrentTags()
}
function drawCurrentTags() {
let html = ''
const tags = parse_text_to_tag_list()
for (const [idx, tag] of tags.entries()) {
html += `${idx + 1}.
`
}
currentTagsList.innerHTML = html
for (const tagLink of currentTagsList.querySelectorAll('.tag')) {
tagLink.onclick = event => {
const currentTags = parse_text_to_tag_list()
const clickedTag = event.target.getAttribute('data-tag')
tagInput.value = currentTags.filter(t => t !== clickedTag).join(TAGSEPERATOR)
tagInput.focus()
}
}
}
} else {
// language=CSS
GM_addStyle(`
#tag-helper {
display: grid;
flex-direction: column;
gap: 10px;
h1 {
font-size: 1.1em;
margin: 0;
}
input[type=text] {
width: 50%;
}
}
`)
const colhead = document.createElement('tr')
colhead.classList.add('colhead_dark')
colhead.innerHTML = 'Tag Helper'
const lastTr = document.querySelector('#userform > table > tbody > tr:last-child')
lastTr.before(colhead)
const hotkeyTr = document.createElement('tr')
hotkeyTr.innerHTML = ` | Hotkeys | `
const td = document.createElement('td')
td.id = 'tag-helper'
hotkeyTr.append(td)
for (const [name, obj] of Object.entries(hotkeys)) {
// language=HTML
td.innerHTML += `
${titlecase(name)}
`
const selects = td.querySelectorAll('select')
selects[selects.length - 1].value = obj.modifier
}
const saveButton = document.createElement('button')
td.append(saveButton)
saveButton.textContent = 'Save'
saveButton.style.width = 'max-content'
saveButton.style.fontSize = 'larger'
saveButton.type = 'button'
saveButton.onclick = () => {
for (const name of Object.keys(hotkeys)) {
const modifierInput = td.querySelector(`select[name="${name}-modifier"]`)
const keysInput = td.querySelector(`input[name="${name}-keys"]`)
hotkeys[name].modifier = modifierInput.value
hotkeys[name].keys = keysInput.value.split(', ')
}
GM_setValue('hotkeys', hotkeys)
saveButton.textContent = 'Saved'
}
colhead.after(hotkeyTr)
}