diff --git a/inventory/static/js/components/combobox.js b/inventory/static/js/components/combobox.js index 4ed1a77..874dbbb 100644 --- a/inventory/static/js/components/combobox.js +++ b/inventory/static/js/components/combobox.js @@ -1,6 +1,39 @@ const ComboBox = globalThis.ComboBox ?? (globalThis.ComboBox = {}); ComboBox.utilities = { + sortList(id) { + const select = document.getElementById(id); + if (!select) return; + + const prevScroll = select.scrollTop; + const prevValue = select.value; + + const options = Array.from(select.options); + let placeholder = null; + if (options.length && ( + options[0].value === '' || + options[0].disabled && (options[0].hidden || options[0].getAttribute('aria-hidden') === 'true') + )) { + placeholder = options.shift(); + } + + const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); + options.sort((a, b) => collator.compare(a.textContent.trim(), b.textContent.trim())); + + select.innerHTML = ''; + if (placeholder) select.appendChild(placeholder); + for (const opt of options) select.appendChild(opt); + + if (prevValue) { + select.value = prevValue; + if (select.value !== prevValue) { + select.selectedIndex = placeholder ? 0 : -1; + } + } + + select.scrollTop = prevScroll; + }, + changeAdd(id) { const input = document.getElementById(`input-${id}`); const add = document.getElementById(`add-${id}`); @@ -65,6 +98,7 @@ ComboBox.utilities = { opt.value = data.id; opt.textContent = data[labelAttr] ?? val; list.appendChild(opt); + this.sortList(id); input.value = ''; }, @@ -81,8 +115,9 @@ ComboBox.utilities = { if (res.ok) { selected.remove(); + this.sortList(id); toastMessage(`Deleted ${id} successfully.`, 'success'); - this.changeRemove(id); + this.handleSelect(id); return; } @@ -106,7 +141,7 @@ ComboBox.utilities = { const opt = list?.selectedOptions?.[0]; if (!opt) return; - const val = opt.value; // id of the row + const val = opt.value; const newText = (input?.value ?? '').trim(); if (!newText) return; @@ -133,7 +168,6 @@ ComboBox.utilities = { return; } - // not ok -> try to show the server error try { data = await res.json(); } catch { data = { error: await res.text() }; } toastMessage(`Edit failed: ${data?.error || `HTTP ${res.status}`}`, 'danger'); } catch (e) {