overhaul: migrated basic JavaScript to TypeScript, began consolidation efforts

This commit is contained in:
matt 2025-10-28 16:17:55 -07:00
parent b994978f60
commit 6a94b982cb
15 changed files with 2012 additions and 74 deletions

View file

@ -628,8 +628,8 @@
} catch(_) {}
})();
</script>
<script src="/static/components.js?v=20250121-1"></script>
<script src="/static/app.js?v=20250826-4"></script>
<script src="/static/js/components.js?v=20251028-1"></script>
<script src="/static/js/app.js?v=20250826-4"></script>
{% if enable_themes %}
<script>
(function(){

View file

@ -3,9 +3,9 @@
{% for cand in candidates %}
<li>
<button type="button" id="cand-{{ loop.index0 }}" class="chip candidate-btn" role="option" data-idx="{{ loop.index0 }}" data-name="{{ cand.value|e }}" data-display="{{ cand.display|e }}"
hx-get="/build/new/inspect?name={{ cand.display|urlencode }}"
hx-target="#newdeck-tags-slot" hx-swap="innerHTML"
hx-on="htmx:afterOnLoad: (function(){ try{ var preferred=this.getAttribute('data-name')||''; var displayed=this.getAttribute('data-display')||preferred; var ci = document.querySelector('input[name=commander]'); if(ci){ ci.value=preferred; try{ ci.selectionStart = ci.selectionEnd = ci.value.length; }catch(_){} try{ ci.dispatchEvent(new Event('input', { bubbles: true })); }catch(_){ } } var nm = document.querySelector('input[name=name]'); if(nm && (!nm.value || !nm.value.trim())){ nm.value=displayed; } }catch(_){ } }).call(this)">
onclick="(function(){ try{ var preferred=this.getAttribute('data-name')||''; var displayed=this.getAttribute('data-display')||preferred; var ci = document.querySelector('input[name=commander]'); if(ci){ ci.value=preferred; try{ ci.selectionStart = ci.selectionEnd = ci.value.length; }catch(_){} } var nm = document.querySelector('input[name=name]'); if(nm && (!nm.value || !nm.value.trim())){ nm.value=displayed; } }catch(_){ } }).call(this)"
hx-get="/build/new/inspect?name={{ cand.value|urlencode }}"
hx-target="#newdeck-tags-slot" hx-swap="innerHTML">
{{ cand.display }}
{% if cand.warning %}
<span aria-hidden="true" style="margin-left:.35rem; font-size:11px; color:#facc15;"></span>

View file

@ -20,9 +20,7 @@
<span>Commander</span>
<input type="text" name="commander" required placeholder="Type a commander name" value="{{ form.commander if form else '' }}" autofocus autocomplete="off" autocapitalize="off" spellcheck="false"
role="combobox" aria-autocomplete="list" aria-controls="newdeck-candidates"
hx-get="/build/new/candidates" hx-trigger="debouncedinput change" hx-target="#newdeck-candidates" hx-sync="this:replace"
data-hx-debounce="220" data-hx-debounce-events="input"
data-hx-debounce-flush="blur" />
hx-get="/build/new/candidates" hx-trigger="input changed delay:220ms, change" hx-target="#newdeck-candidates" hx-sync="this:replace" />
</label>
<small class="muted block mt-1">Start typing to see matches, then select one to load themes.</small>
<div id="newdeck-candidates" class="muted text-xs min-h-[1.1em]"></div>

View file

@ -32,16 +32,26 @@
if(!(target.tagName && target.tagName.toLowerCase() === 'body')) return;
var init = document.getElementById('builder-init');
var preset = init && init.dataset ? (init.dataset.commander || '') : '';
if(!preset) return;
console.log('[Quick-build] DEBUG: preset=', preset);
if(!preset) {
console.log('[Quick-build] DEBUG: No preset, exiting');
return;
}
var input = document.querySelector('input[name="commander"]');
console.log('[Quick-build] DEBUG: Found input?', !!input);
if(input){
if(!input.value){ input.value = preset; }
console.log('[Quick-build] DEBUG: Input current value:', input.value);
if(!input.value){
input.value = preset;
console.log('[Quick-build] DEBUG: Set input to:', preset);
}
try { input.dispatchEvent(new Event('input', {bubbles:true})); } catch(_){ }
try { input.focus(); } catch(_){ }
}
// If htmx is available, auto-load the inspect view for an exact preset name.
try {
if (window.htmx && preset && typeof window.htmx.ajax === 'function'){
console.log('[Quick-build] DEBUG: Calling inspect with:', preset);
window.htmx.ajax('GET', '/build/new/inspect?name=' + encodeURIComponent(preset), { target: '#newdeck-tags-slot', swap: 'innerHTML' });
// Also try to load multi-copy suggestions based on current radio defaults
setTimeout(function(){

View file

@ -5,34 +5,22 @@
{% set placeholder_pixel = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==" %}
<article class="commander-row" data-commander-slug="{{ record.slug }}" data-hover-simple="true">
<div class="commander-thumb">
{% set small = record.image_small_url or record.image_normal_url %}
{% set normal = record.image_normal_url or small %}
{% set small = record.display_name|card_image('small') %}
{% set normal = record.display_name|card_image('normal') %}
<img
src="{{ placeholder_pixel }}"
src="{{ small }}"
srcset="{{ small }} 160w, {{ normal }} 488w"
sizes="(max-width: 900px) 60vw, 160px"
alt="{{ record.display_name }} card art"
loading="lazy"
decoding="async"
width="160"
height="223"
data-lazy-image="commander"
data-lazy-src="{{ small }}"
data-lazy-srcset="{{ small }} 160w, {{ normal }} 488w"
data-lazy-sizes="(max-width: 900px) 60vw, 160px"
data-card-name="{{ record.display_name }}"
data-original-name="{{ record.name }}"
data-hover-simple="true"
class="commander-thumb-img"
/>
<noscript>
<img
src="{{ small }}"
srcset="{{ small }} 160w, {{ normal }} 488w"
sizes="160px"
alt="{{ record.display_name }} card art"
width="160"
height="223"
/>
</noscript>
</div>
<div class="commander-main">
<div class="commander-header">