58 lines
2.2 KiB
JavaScript
58 lines
2.2 KiB
JavaScript
(() => {
|
|
document.addEventListener('submit', event => {
|
|
const message = event.target.dataset.confirm;
|
|
if (message && !window.confirm(message)) event.preventDefault();
|
|
});
|
|
|
|
const root = document.querySelector('[data-admin-app]');
|
|
if (!root) return;
|
|
|
|
const csrf = root.dataset.csrf;
|
|
const rows = root.querySelector('[data-author-rows]');
|
|
const template = root.querySelector('[data-author-template]');
|
|
const searchUrl = root.dataset.authorSearch;
|
|
|
|
function addAuthorRow(id = '', name = '', margin = '') {
|
|
const row = template.content.firstElementChild.cloneNode(true);
|
|
row.querySelector('[data-author-id]').value = id;
|
|
row.querySelector('[data-author-name]').value = name;
|
|
row.querySelector('[data-margin]').value = margin;
|
|
rows.appendChild(row);
|
|
bindSearch(row);
|
|
}
|
|
|
|
function bindSearch(row) {
|
|
const input = row.querySelector('[data-author-name]');
|
|
const id = row.querySelector('[data-author-id]');
|
|
const list = row.querySelector('[data-suggestions]');
|
|
let timer;
|
|
input.addEventListener('input', () => {
|
|
id.value = '';
|
|
clearTimeout(timer);
|
|
const term = input.value.trim();
|
|
if (term.length < 2) { list.replaceChildren(); return; }
|
|
timer = setTimeout(async () => {
|
|
const response = await fetch(`${searchUrl}?q=${encodeURIComponent(term)}`, {
|
|
credentials: 'same-origin',
|
|
headers: { 'X-CSRF-Token': csrf }
|
|
});
|
|
if (!response.ok) return;
|
|
const authors = await response.json();
|
|
list.replaceChildren(...authors.map(author => {
|
|
const item = document.createElement('li');
|
|
const button = document.createElement('button');
|
|
button.type = 'button'; button.textContent = author.name;
|
|
button.addEventListener('click', () => { input.value = author.name; id.value = author.id; list.replaceChildren(); });
|
|
item.appendChild(button); return item;
|
|
}));
|
|
}, 180);
|
|
});
|
|
}
|
|
|
|
root.querySelector('[data-add-author]').addEventListener('click', () => addAuthorRow());
|
|
root.addEventListener('click', event => {
|
|
if (event.target.matches('[data-remove-author]')) event.target.closest('[data-author-row]').remove();
|
|
});
|
|
root.querySelectorAll('[data-author-row]').forEach(bindSearch);
|
|
})();
|