From 9ea6fdfb39facdb9b02f3359367873e4ba9d521d Mon Sep 17 00:00:00 2001 From: Luna D Date: Sat, 8 Jun 2024 11:47:09 -0400 Subject: [PATCH] Convert tagsmisc and sources scripts to TypeScript --- assets/js/{sources.js => sources.ts} | 12 +++-- assets/js/tagsmisc.js | 56 ---------------------- assets/js/tagsmisc.ts | 69 ++++++++++++++++++++++++++++ assets/types/ujs.ts | 11 +++++ 4 files changed, 87 insertions(+), 61 deletions(-) rename assets/js/{sources.js => sources.ts} (71%) delete mode 100644 assets/js/tagsmisc.js create mode 100644 assets/js/tagsmisc.ts create mode 100644 assets/types/ujs.ts diff --git a/assets/js/sources.js b/assets/js/sources.ts similarity index 71% rename from assets/js/sources.js rename to assets/js/sources.ts index bb4ae3ad..b4bc51ec 100644 --- a/assets/js/sources.js +++ b/assets/js/sources.ts @@ -1,4 +1,7 @@ +import { assertNotNull } from './utils/assert'; +import { $ } from './utils/dom'; import { inputDuplicatorCreator } from './input-duplicator'; +import '../types/ujs'; function setupInputs() { inputDuplicatorCreator({ @@ -9,12 +12,13 @@ function setupInputs() { }); } -function imageSourcesCreator() { +export function imageSourcesCreator() { setupInputs(); - document.addEventListener('fetchcomplete', ({ target, detail }) => { - const sourceSauce = document.querySelector('.js-sourcesauce'); + document.addEventListener('fetchcomplete', ({ target, detail }) => { if (target.matches('#source-form')) { + const sourceSauce = assertNotNull($('.js-sourcesauce')); + detail.text().then(text => { sourceSauce.outerHTML = text; setupInputs(); @@ -22,5 +26,3 @@ function imageSourcesCreator() { } }); } - -export { imageSourcesCreator }; diff --git a/assets/js/tagsmisc.js b/assets/js/tagsmisc.js deleted file mode 100644 index 29dc9dbe..00000000 --- a/assets/js/tagsmisc.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Tags Misc - */ - -import { $$ } from './utils/dom'; -import store from './utils/store'; -import { initTagDropdown } from './tags'; -import { setupTagsInput, reloadTagsInput } from './tagsinput'; - -function tagInputButtons({target}) { - const actions = { - save(tagInput) { - store.set('tag_input', tagInput.value); - }, - load(tagInput) { - // If entry 'tag_input' does not exist, try to use the current list - tagInput.value = store.get('tag_input') || tagInput.value; - reloadTagsInput(tagInput); - }, - clear(tagInput) { - tagInput.value = ''; - reloadTagsInput(tagInput); - }, - }; - - for (const action in actions) { - if (target.matches(`#tagsinput-${action}`)) actions[action](document.getElementById('image_tag_input')); - } -} - -function setupTags() { - $$('.js-tag-block').forEach(el => { - setupTagsInput(el); - el.classList.remove('js-tag-block'); - }); -} - -function updateTagSauce({target, detail}) { - const tagSauce = document.querySelector('.js-tagsauce'); - - if (target.matches('#tags-form')) { - detail.text().then(text => { - tagSauce.outerHTML = text; - setupTags(); - initTagDropdown(); - }); - } -} - -function setupTagEvents() { - setupTags(); - document.addEventListener('fetchcomplete', updateTagSauce); - document.addEventListener('click', tagInputButtons); -} - -export { setupTagEvents }; diff --git a/assets/js/tagsmisc.ts b/assets/js/tagsmisc.ts new file mode 100644 index 00000000..5ae6874a --- /dev/null +++ b/assets/js/tagsmisc.ts @@ -0,0 +1,69 @@ +/** + * Tags Misc + */ + +import { assertType, assertNotNull } from './utils/assert'; +import { $, $$ } from './utils/dom'; +import store from './utils/store'; +import { initTagDropdown } from './tags'; +import { setupTagsInput, reloadTagsInput } from './tagsinput'; +import '../types/ujs'; + +type TagInputActionFunction = (tagInput: HTMLTextAreaElement | null) => void; +type TagInputActionList = Record; + +function tagInputButtons(event: MouseEvent) { + const target = assertType(event.target, HTMLElement); + + const actions: TagInputActionList = { + save(tagInput: HTMLTextAreaElement | null) { + tagInput && store.set('tag_input', tagInput.value); + }, + load(tagInput: HTMLTextAreaElement | null) { + if (!tagInput) { return; } + + // If entry 'tag_input' does not exist, try to use the current list + tagInput.value = store.get('tag_input') || tagInput.value; + reloadTagsInput(tagInput); + }, + clear(tagInput: HTMLTextAreaElement | null) { + if (!tagInput) { return; } + + tagInput.value = ''; + reloadTagsInput(tagInput); + }, + }; + + for (const [ name, action ] of Object.entries(actions)) { + if (target && target.matches(`#tagsinput-${name}`)) { + action($('image_tag_input')); + } + } +} + +function setupTags() { + $$('.js-tag-block').forEach(el => { + setupTagsInput(el); + el.classList.remove('js-tag-block'); + }); +} + +function updateTagSauce({ target, detail }: FetchcompleteEvent) { + if (target.matches('#tags-form')) { + const tagSauce = assertNotNull($('.js-tagsauce')); + + detail.text().then(text => { + tagSauce.outerHTML = text; + setupTags(); + initTagDropdown(); + }); + } +} + +function setupTagEvents() { + setupTags(); + document.addEventListener('fetchcomplete', updateTagSauce); + document.addEventListener('click', tagInputButtons); +} + +export { setupTagEvents }; diff --git a/assets/types/ujs.ts b/assets/types/ujs.ts new file mode 100644 index 00000000..f9cb88f5 --- /dev/null +++ b/assets/types/ujs.ts @@ -0,0 +1,11 @@ +export {}; + +declare global { + interface FetchcompleteEvent extends CustomEvent { + target: HTMLElement, + } + + interface GlobalEventHandlersEventMap { + fetchcomplete: FetchcompleteEvent; + } +}