fix indentation

This commit is contained in:
stefan.tollkuehn committed 2026-10-23 13:52:45 +02:00
1 parent 00dbbe3421
commit e1a3fd12f0
1 file changed
+144 -144
+144 -144
View File
@@ -10,178 +10,178 @@
* datalist rendered by the server. * datalist rendered by the server.
*/ */
(function () { (function () {
'use strict'; 'use strict';
var DEBOUNCE_MS = 250; var DEBOUNCE_MS = 250;
var SEPARATOR = /[;,]/; var SEPARATOR = /[;,]/;
var input = document.getElementById('atocal-attendees'); var input = document.getElementById('atocal-attendees');
if (!input) { if (!input) {
return; return;
} }
var searchUrl = input.dataset.searchUrl; var searchUrl = input.dataset.searchUrl;
if (!searchUrl) { if (!searchUrl) {
return; return;
} }
var list = document.createElement('ul'); var list = document.createElement('ul');
list.className = 'atocal-suggestions'; list.className = 'atocal-suggestions';
list.hidden = true; list.hidden = true;
list.setAttribute('role', 'listbox'); list.setAttribute('role', 'listbox');
/* The wrapper span provides position: relative */ /* The wrapper span provides position: relative */
input.parentNode.appendChild(list); input.parentNode.appendChild(list);
/* The native datalist popup would double the custom one */ /* The native datalist popup would double the custom one */
input.removeAttribute('list'); input.removeAttribute('list');
var debounceTimer = null; var debounceTimer = null;
var requestSeq = 0; var requestSeq = 0;
var suggestions = []; var suggestions = [];
var activeIndex = -1; var activeIndex = -1;
function fragment() { function fragment() {
var parts = input.value.split(SEPARATOR); var parts = input.value.split(SEPARATOR);
return parts[parts.length - 1].trim(); return parts[parts.length - 1].trim();
} }
function hide() { function hide() {
list.hidden = true; list.hidden = true;
list.replaceChildren(); list.replaceChildren();
suggestions = []; suggestions = [];
activeIndex = -1; activeIndex = -1;
input.setAttribute('aria-expanded', 'false'); input.setAttribute('aria-expanded', 'false');
input.removeAttribute('aria-activedescendant'); input.removeAttribute('aria-activedescendant');
} }
function commit(email) { function commit(email) {
var parts = input.value.split(/([;,])/); var parts = input.value.split(/([;,])/);
parts.pop(); parts.pop();
var prefix = parts.join('').replace(/\s+$/, ''); var prefix = parts.join('').replace(/\s+$/, '');
input.value = prefix === '' ? email + ', ' : prefix + ' ' + email + ', '; input.value = prefix === '' ? email + ', ' : prefix + ' ' + email + ', ';
hide(); hide();
input.focus(); input.focus();
} }
function moveSelection(offset) { function moveSelection(offset) {
activeIndex = (activeIndex + offset + suggestions.length) % suggestions.length; activeIndex = (activeIndex + offset + suggestions.length) % suggestions.length;
list.childNodes.forEach(function (option, i) { list.childNodes.forEach(function (option, i) {
option.classList.toggle('atocal-active', i === activeIndex); option.classList.toggle('atocal-active', i === activeIndex);
}); });
input.setAttribute('aria-activedescendant', 'atocal-suggestion-' + activeIndex); input.setAttribute('aria-activedescendant', 'atocal-suggestion-' + activeIndex);
} }
function render(contacts) { function render(contacts) {
hide(); hide();
if (contacts.length === 0) { if (contacts.length === 0) {
return; return;
} }
suggestions = contacts; suggestions = contacts;
contacts.forEach(function (contact, i) { contacts.forEach(function (contact, i) {
var option = document.createElement('li'); var option = document.createElement('li');
option.id = 'atocal-suggestion-' + i; option.id = 'atocal-suggestion-' + i;
option.setAttribute('role', 'option'); option.setAttribute('role', 'option');
var button = document.createElement('button'); var button = document.createElement('button');
button.type = 'button'; button.type = 'button';
button.tabIndex = -1; button.tabIndex = -1;
button.addEventListener('mousedown', function (event) { button.addEventListener('mousedown', function (event) {
/* keep focus on the input */ /* keep focus on the input */
event.preventDefault(); event.preventDefault();
commit(contact.email); commit(contact.email);
}); });
var name = document.createElement('span'); var name = document.createElement('span');
name.className = 'atocal-suggestion-name'; name.className = 'atocal-suggestion-name';
name.textContent = contact.name === '' ? contact.email : contact.name; name.textContent = contact.name === '' ? contact.email : contact.name;
var email = document.createElement('span'); var email = document.createElement('span');
email.className = 'atocal-suggestion-email'; email.className = 'atocal-suggestion-email';
email.textContent = contact.email; email.textContent = contact.email;
button.appendChild(name); button.appendChild(name);
button.appendChild(email); button.appendChild(email);
option.appendChild(button); option.appendChild(button);
list.appendChild(option); list.appendChild(option);
}); });
list.hidden = false; list.hidden = false;
input.setAttribute('aria-expanded', 'true'); input.setAttribute('aria-expanded', 'true');
} }
function search(query) { function search(query) {
var seq = ++requestSeq; var seq = ++requestSeq;
fetch(searchUrl + '?query=' + encodeURIComponent(query), { fetch(searchUrl + '?query=' + encodeURIComponent(query), {
headers: { Accept: 'application/json' } headers: { Accept: 'application/json' }
}) })
.then(function (response) { .then(function (response) {
if (!response.ok) { if (!response.ok) {
throw new Error('search failed'); throw new Error('search failed');
} }
return response.json(); return response.json();
}) })
.then(function (contacts) { .then(function (contacts) {
if (seq === requestSeq) { if (seq === requestSeq) {
render(Array.isArray(contacts) ? contacts : []); render(Array.isArray(contacts) ? contacts : []);
} }
}) })
.catch(function () { .catch(function () {
if (seq === requestSeq) { if (seq === requestSeq) {
hide(); hide();
} }
}); });
} }
input.addEventListener('input', function () { input.addEventListener('input', function () {
clearTimeout(debounceTimer); clearTimeout(debounceTimer);
var query = fragment(); var query = fragment();
if (query === '') { if (query === '') {
hide(); hide();
return; return;
} }
debounceTimer = setTimeout(function () { debounceTimer = setTimeout(function () {
search(query); search(query);
}, DEBOUNCE_MS); }, DEBOUNCE_MS);
}); });
input.addEventListener('keydown', function (event) { input.addEventListener('keydown', function (event) {
if (list.hidden) { if (list.hidden) {
return; return;
} }
switch (event.key) { switch (event.key) {
case 'ArrowDown': case 'ArrowDown':
moveSelection(1); moveSelection(1);
event.preventDefault(); event.preventDefault();
break; break;
case 'ArrowUp': case 'ArrowUp':
moveSelection(-1); moveSelection(-1);
event.preventDefault(); event.preventDefault();
break; break;
case 'Enter': case 'Enter':
if (activeIndex >= 0) { if (activeIndex >= 0) {
commit(suggestions[activeIndex].email); commit(suggestions[activeIndex].email);
event.preventDefault(); event.preventDefault();
} }
break; break;
case 'Escape': case 'Escape':
hide(); hide();
break; break;
} }
}); });
document.addEventListener('click', function (event) { document.addEventListener('click', function (event) {
if (!list.hidden && event.target !== input && !list.contains(event.target)) { if (!list.hidden && event.target !== input && !list.contains(event.target)) {
hide(); hide();
} }
}); });
})(); })();