Refactor ComboBoxWidget; enhance createOption and sortOptions functions, update onAdd parameter in render_combobox macro for improved usability and maintainability

This commit is contained in:
Yaro Kasear 2025-06-20 11:55:36 -05:00
parent b182e30c43
commit 3c9806bd34
3 changed files with 62 additions and 19 deletions

View file

@ -1,11 +1,28 @@
console.log('ComboBoxWidget loaded');
const ComboBoxWidget = (() => { const ComboBoxWidget = (() => {
let tempIdCounter = -1;
function createOption(text, value = null) {
const option = document.createElement('option');
option.textContent = text;
option.value = value ?? (tempIdCounter--);
return option;
}
function sortOptions(selectElement) {
const sorted = Array.from(selectElement.options)
.sort((a, b) => a.text.localeCompare(b.text));
selectElement.innerHTML = '';
sorted.forEach(option => selectElement.appendChild(option));
}
function initComboBox(ns, config = {}) { function initComboBox(ns, config = {}) {
const input = document.querySelector(`#${ns}-input`); const input = document.querySelector(`#${ns}-input`);
const list = document.querySelector(`#${ns}-list`); const list = document.querySelector(`#${ns}-list`);
const addBtn = document.querySelector(`#${ns}-add`); const addBtn = document.querySelector(`#${ns}-add`);
const removeBtn = document.querySelector(`#${ns}-remove`); const removeBtn = document.querySelector(`#${ns}-remove`);
let currentlyEditing = null; let currentlyEditing = null;
let tempIdCounter = -1;
if (!input || !list || !addBtn || !removeBtn) { if (!input || !list || !addBtn || !removeBtn) {
console.warn(`ComboBoxWidget: Missing elements for namespace '${ns}'`); console.warn(`ComboBoxWidget: Missing elements for namespace '${ns}'`);
@ -58,16 +75,13 @@ const ComboBoxWidget = (() => {
} }
currentlyEditing = null; currentlyEditing = null;
} else { } else {
const option = document.createElement('option');
option.textContent = newItem;
option.value = tempIdCounter--;
if (config.onAdd) { if (config.onAdd) {
config.onAdd(option); config.onAdd(newItem, list, createOption);
} } else {
const option = createOption(newItem);
list.appendChild(option); list.appendChild(option);
} }
}
input.value = ''; input.value = '';
addBtn.disabled = true; addBtn.disabled = true;
@ -93,16 +107,11 @@ const ComboBoxWidget = (() => {
removeBtn.disabled = true; removeBtn.disabled = true;
updateAddButtonIcon(); updateAddButtonIcon();
}); });
function sortOptions(selectElement) {
const sorted = Array.from(selectElement.options)
.sort((a, b) => a.text.localeCompare(b.text));
selectElement.innerHTML = '';
sorted.forEach(option => selectElement.appendChild(option));
}
} }
return { return {
initComboBox initComboBox,
createOption,
sortOptions
}; };
})(); })();

View file

@ -24,7 +24,7 @@
<script> <script>
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
ComboBoxWidget.initComboBox("{{ id }}", { ComboBoxWidget.initComboBox("{{ id }}", {
{% if onAdd %}onAdd: function(option) { {{ onAdd | safe }} },{% endif %} {% if onAdd %}onAdd: function(newItem, list, createOption) { {{ onAdd | safe }} },{% endif %}
{% if onRemove %}onRemove: function(option) { {{ onRemove | safe }} },{% endif %} {% if onRemove %}onRemove: function(option) { {{ onRemove | safe }} },{% endif %}
{% if onEdit %}onEdit: function(option) { {{ onEdit | safe }} }{% endif %} {% if onEdit %}onEdit: function(option) { {{ onEdit | safe }} }{% endif %}
}); });

View file

@ -60,6 +60,9 @@
<div class="row"> <div class="row">
{% set room_editor %} {% set room_editor %}
const roomEditor = new bootstrap.Modal(document.getElementById('roomEditor')); const roomEditor = new bootstrap.Modal(document.getElementById('roomEditor'));
const roomNameInput = document.getElementById('roomName');
roomNameInput.value = document.getElementById('room-input').value;
roomEditor.show(); roomEditor.show();
{% endset %} {% endset %}
<div class="col"> <div class="col">
@ -111,11 +114,42 @@
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-danger" data-bs-dismiss="modal"
<button type="button" class="btn btn-primary">Save</button> id="roomEditorCancelButton">Cancel</button>
<button type="button" class="btn btn-primary" id="roomEditorSaveButton">Save</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
{% endblock %} {% endblock %}
{% block script %}
document.addEventListener('DOMContentLoaded', () => {
const modal = document.getElementById('roomEditor');
const saveButton = document.getElementById('roomEditorSaveButton');
const cancelButton = document.getElementById('roomEditorCancelButton');
saveButton.addEventListener('click', () => {
console.log('Save button clicked');
const name = document.getElementById('roomName').value;
const section = document.getElementById('roomSection').value;
const func = document.getElementById('roomFunction').value;
if (name.trim()) {
const newRoom = ComboBoxWidget.createOption(`${name}`, null);
document.getElementById('room-list').appendChild(newRoom);
ComboBoxWidget.sortOptions(document.getElementById('room-list'));
bootstrap.Modal.getInstance(modal).hide();
} else {
alert('Please enter a room name.');
}
});
cancelButton.addEventListener('click', () => {
console.log('Cancel button clicked');
bootstrap.Modal.getInstance(modal).hide();
});
});
{% endblock %}