async function getHTML(endpoint, options = {}) { let query = {}; if (options._query !== undefined) { query = options._query; delete options._query; } const params = new URLSearchParams(query); const res = await fetch(`${endpoint}?${params}`, options); return { body: await res.text(), status: res.status }; } const validateBase64Img = dataURL => new Promise(resolve => { const img = new Image(); img.onload = () => { resolve(img.width === 88 && img.height === 31); }; img.src = dataURL; }); export const b = { init: 'badgeEditorInit', } const badgeEditorEndpoint = '/hyperapi/badges/editor/' const MAX_BADGES = 10; let badgesCount = 0; let customImageDatas = {}; export async function badgeEditorInit(_, __, el) { const res = await getHTML(badgeEditorEndpoint); if (res.status != 200) { return; } el.innerHTML = res.body; badgesCount = el.querySelectorAll('.sortable-item').length; b.trigger('badgeEditorAssignImgId'); b.trigger('setBadgeCount'); } export function badgeEditorAssignImgId(_, __, el) { if (el.dataset.imgId) return; const id = b.uuid(); const filePicker = el.querySelector('input[type=file]'); const img = el.querySelector('img.badge-button'); console.log(img); el.dataset.imgId = id; filePicker.dataset.imgId = id; img.dataset.imgId = id; } export function badgeEditorSetPreview(ev, sender, el) { if (!sender.parentNode.contains(el)) return; const selectedItem = sender.selectedOptions[0]; if (selectedItem.value !== 'custom') { el.src = selectedItem.dataset.filePath; } else if (customImageDatas[el.dataset.imgId]) { el.src = customImageDatas[el.dataset.imgId]; } else { el.removeAttribute('src'); } } export function badgeEditorSetPreviewCustom(payload, _, el) { if (!payload.badge.contains(el)) return; if (!customImageDatas[el.dataset.imgId]) { el.removeAttribute('src'); } else { el.src = customImageDatas[el.dataset.imgId]; } } export function badgeEditorToggleFilePicker(ev, sender, el) { if (!sender.parentNode.parentNode.contains(el)) return; const selectedItem = sender.selectedOptions[0]; const picker = el.querySelector('input[type=file]'); if (selectedItem.value !== 'custom') { el.classList.add('hidden'); picker.required = false; picker.setCustomValidity(''); } else { el.classList.remove('hidden'); picker.required = true; picker.setCustomValidity(picker.dataset.validity || ''); } } export function badgeEditorAddBadge(ev, sender, el) { // TODO: page templates do not get updated on mutation const badge = document.getElementById('badge-template').innerText; el.innerHTML += badge; b.trigger('badgeEditorAssignImgId'); badgesCount++; b.trigger('setBadgeCount'); } export function badgeEditorDelete(ev, sender, el) { if (!el.contains(sender)) return; el.remove(); badgesCount--; b.trigger('setBadgeCount'); } export function badgeEditorShowFilePicker(ev, sender, el) { if (sender.nextElementSibling !== el) return; el.showPicker(); } export async function badgeEditorFileSelected(ev, sender, el) { const file = sender.files[0]; const badge = sender.parentNode.parentNode; if ( !['image/png', 'image/jpeg', 'image/jpg', 'image/webp'].includes(file.type) ) { sender.dataset.validity = 'The badge file must be an image.'; sender.setCustomValidity(sender.dataset.validity); sender.reportValidity(); customImageDatas[sender.dataset.imgId] = null; b.send({ badge: badge }, 'badgeEditorSetPreviewCustom'); return; } if (file.size >= 1000 * 500) { sender.dataset.validity = 'The badge image must be smaller than 500KB.'; sender.setCustomValidity(sender.dataset.validity); sender.reportValidity(); customImageDatas[sender.dataset.imgId] = null; b.send({ badge: badge }, 'badgeEditorSetPreviewCustom'); return; } const reader = new FileReader(); reader.onload = async e => { const dimsValid = await validateBase64Img(e.target.result); if (!dimsValid) { sender.setCustomValidity('The badge image must be exactly 88x31 pixels.'); sender.reportValidity(); customImageDatas[sender.dataset.imgId] = null; b.send({ badge: badge }, 'badgeEditorSetPreviewCustom'); return; } customImageDatas[sender.dataset.imgId] = e.target.result; sender.dataset.validity = ''; sender.setCustomValidity(''); b.send({ badge: badge }, 'badgeEditorSetPreviewCustom'); } reader.readAsDataURL(file); } export function setBadgeCount(_, __, el) { if (el instanceof HTMLButtonElement) { el.disabled = badgesCount === MAX_BADGES; } else { el.innerText = `${badgesCount}/${MAX_BADGES}`; } }