tagliatelle

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit fb0b8116106fb4ab360dd0326bf0313d850040d9
parent 7340252549aa10341fd937ef973bcad54a49a74d
Author: breadcat <breadcat@users.noreply.github.com>
Date:   Thu,  7 May 2026 16:21:22 +0100

Reduce space taken displaying alias groups

Diffstat:
Mstatic/style.css | 16++++++++++++++--
Mstatic/tag-alias.js | 170+++++++++++++++++++++++++++++++++++++++++++------------------------------------
2 files changed, 106 insertions(+), 80 deletions(-)

diff --git a/static/style.css b/static/style.css @@ -188,4 +188,17 @@ div.config-split {flex: 1} .operation-desc{font-size:12px;color:#666} /* list filter input box */ -.list-filter-input {display: block; margin: 1rem 0; padding: 0.4rem 0.6rem; font-size: 1rem; width: 100%; max-width: 400px} -\ No newline at end of file +.list-filter-input {display: block; margin: 1rem 0; padding: 0.4rem 0.6rem; font-size: 1rem; width: 100%; max-width: 400px} + +/* tag aliases */ +.alias-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:6px 4px;border-bottom:1px solid #eee} +.alias-row:last-child{border-bottom:none} +.alias-input{padding:4px 7px;font-size:13px;border:1px solid #ccc;border-radius:3px;background:#fff} +.alias-input:focus{outline:0;border-color:#666} +.alias-input--category{width:110px;font-weight:600} +.alias-input--value{width:90px} +.alias-separator{color:#aaa;font-size:13px;user-select:none} +.alias-btn{padding:3px 7px;font-size:12px;border:1px solid #ccc;border-radius:3px;background:#f5f5f5;cursor:pointer;white-space:nowrap;line-height:1.4} +.alias-btn:hover{background:#e8e8e8} +.alias-btn--remove{color:#c00;border-color:#e0b0b0;background:#fff5f5} +.alias-btn--remove:hover{background:#fde8e8} diff --git a/static/tag-alias.js b/static/tag-alias.js @@ -1,111 +1,127 @@ -// Initialize from the global variable passed from the template let aliasGroups = window.initialAliasGroups || []; function renderAliasGroups() { const container = document.getElementById('alias-groups'); container.innerHTML = ''; - aliasGroups.forEach((group, groupIndex) => { - const groupDiv = document.createElement('div'); - groupDiv.style.cssText = 'border: 1px solid #ddd; padding: 15px; margin-bottom: 15px; border-radius: 4px;'; - - groupDiv.innerHTML = ` - <div style="margin-bottom: 10px;"> - <label style="display: block; font-weight: bold; margin-bottom: 5px;">Category:</label> - <input type="text" - value="${escapeHtml(group.category)}" - onchange="updateCategory(${groupIndex}, this.value)" - style="width: 200px; padding: 6px; font-size: 14px;" - placeholder="e.g., colour"> - </div> - - <div style="margin-bottom: 10px;"> - <label style="display: block; font-weight: bold; margin-bottom: 5px;">Aliased Values:</label> - <div id="aliases-${groupIndex}"></div> - <button onclick="addAlias(${groupIndex})" type="button" class="text-button">+ Add Value</button> - </div> - - <button onclick="removeAliasGroup(${groupIndex})" type="button" class="text-button">Remove Group</button> - `; - - container.appendChild(groupDiv); - renderAliases(groupIndex); + aliasGroups.forEach((group, gi) => { + if (!group.aliases) group.aliases = []; + + const row = document.createElement('div'); + row.className = 'alias-row'; + row.dataset.group = gi; + + // Category input + const catInput = document.createElement('input'); + catInput.type = 'text'; + catInput.className = 'alias-input alias-input--category'; + catInput.value = group.category; + catInput.placeholder = 'category'; + catInput.addEventListener('change', e => { aliasGroups[gi].category = e.target.value; }); + row.appendChild(catInput); + + // Arrow separator + const arrow = document.createElement('span'); + arrow.className = 'alias-separator'; + arrow.textContent = '→'; + row.appendChild(arrow); + + // Alias value inputs + const valuesWrapper = document.createElement('span'); + valuesWrapper.id = `aliases-${gi}`; + valuesWrapper.style.cssText = 'display:inline-flex; gap:4px; flex-wrap:wrap; align-items:center;'; + row.appendChild(valuesWrapper); + renderAliasValues(gi, valuesWrapper); + + // + Value button + const addBtn = document.createElement('button'); + addBtn.type = 'button'; + addBtn.className = 'alias-btn'; + addBtn.textContent = '+ Value'; + addBtn.addEventListener('click', () => addAlias(gi)); + row.appendChild(addBtn); + + // Remove group button + const removeBtn = document.createElement('button'); + removeBtn.type = 'button'; + removeBtn.className = 'alias-btn alias-btn--remove'; + removeBtn.textContent = '✕ Group'; + removeBtn.addEventListener('click', () => removeAliasGroup(gi)); + row.appendChild(removeBtn); + + container.appendChild(row); }); } -function renderAliases(groupIndex) { - const container = document.getElementById(`aliases-${groupIndex}`); - container.innerHTML = ''; - - const group = aliasGroups[groupIndex]; - if (!group.aliases) { - group.aliases = []; - } - - group.aliases.forEach((alias, aliasIndex) => { - const aliasDiv = document.createElement('div'); - aliasDiv.style.cssText = 'display: flex; gap: 10px; margin-bottom: 5px; align-items: center;'; - - aliasDiv.innerHTML = ` - <input type="text" - value="${escapeHtml(alias)}" - onchange="updateAlias(${groupIndex}, ${aliasIndex}, this.value)" - style="flex: 1; padding: 6px; font-size: 14px;" - placeholder="e.g., blue"> - <button onclick="removeAlias(${groupIndex}, ${aliasIndex})" type="button" class="text-button">Remove</button> - `; - - container.appendChild(aliasDiv); +function renderAliasValues(gi, wrapper) { + if (!wrapper) wrapper = document.getElementById(`aliases-${gi}`); + wrapper.innerHTML = ''; + + aliasGroups[gi].aliases.forEach((alias, ai) => { + if (ai > 0) { + const comma = document.createElement('span'); + comma.className = 'alias-separator'; + comma.textContent = ','; + wrapper.appendChild(comma); + } + + const input = document.createElement('input'); + input.type = 'text'; + input.className = 'alias-input alias-input--value'; + input.value = alias; + input.placeholder = 'value'; + input.addEventListener('change', e => updateAlias(gi, ai, e.target.value)); + + // Double-click to remove a single value + input.title = 'Double-click to remove'; + input.addEventListener('dblclick', () => removeAlias(gi, ai)); + + wrapper.appendChild(input); }); } function addAliasGroup() { - aliasGroups.push({ - category: '', - aliases: ['', ''] - }); + aliasGroups.push({ category: '', aliases: ['', ''] }); renderAliasGroups(); } -function removeAliasGroup(groupIndex) { +function removeAliasGroup(gi) { if (confirm('Remove this alias group?')) { - aliasGroups.splice(groupIndex, 1); + aliasGroups.splice(gi, 1); renderAliasGroups(); } } -function updateCategory(groupIndex, value) { - aliasGroups[groupIndex].category = value; +function updateCategory(gi, value) { + aliasGroups[gi].category = value; } -function addAlias(groupIndex) { - aliasGroups[groupIndex].aliases.push(''); - renderAliases(groupIndex); +function addAlias(gi) { + aliasGroups[gi].aliases.push(''); + renderAliasValues(gi); } -function removeAlias(groupIndex, aliasIndex) { - aliasGroups[groupIndex].aliases.splice(aliasIndex, 1); - renderAliases(groupIndex); +function removeAlias(gi, ai) { + aliasGroups[gi].aliases.splice(ai, 1); + renderAliasValues(gi); } -function updateAlias(groupIndex, aliasIndex, value) { - aliasGroups[groupIndex].aliases[aliasIndex] = value; +function updateAlias(gi, ai, value) { + aliasGroups[gi].aliases[ai] = value; } -document.getElementById('aliases-form').addEventListener('submit', function(e) { - // Filter out incomplete groups (need a category and at least 2 aliases) +// submit form +document.getElementById('aliases-form').addEventListener('submit', function () { const cleanedGroups = aliasGroups - .filter(group => group.category && group.aliases && group.aliases.length > 0) - .map(group => ({ - category: group.category.trim(), - aliases: group.aliases.filter(a => a && a.trim()).map(a => a.trim()) + .filter(g => g.category && g.aliases && g.aliases.length > 0) + .map(g => ({ + category: g.category.trim(), + aliases: g.aliases.filter(a => a && a.trim()).map(a => a.trim()) })) - .filter(group => group.aliases.length >= 2); + .filter(g => g.aliases.length >= 2); - // Remove any previously-injected hidden fields from a prior submit this.querySelectorAll('input[data-generated]').forEach(el => el.remove()); - // Append one hidden field per value — no JSON cleanedGroups.forEach((group, gi) => { appendHidden(this, `aliases[${gi}][category]`, group.category); group.aliases.forEach((alias, ai) => { @@ -123,7 +139,5 @@ function appendHidden(form, name, value) { form.appendChild(input); } -// Initial render -document.addEventListener('DOMContentLoaded', function() { - renderAliasGroups(); -}); +// initialise +document.addEventListener('DOMContentLoaded', renderAliasGroups);