Create app.js
Browse files
app.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const $=s=>document.querySelector(s);
|
| 2 |
+
const fams=[...new Set(TAX.map(t=>t[2]))];
|
| 3 |
+
const fsel=$('#fam'),csel=$('#coord');
|
| 4 |
+
fams.forEach(f=>fsel.add(new Option(f,f)));
|
| 5 |
+
function fillCoords(){csel.length=1;TAX.filter(t=>!fsel.value||t[2]===fsel.value).forEach(t=>csel.add(new Option(t[1],t[0])))}
|
| 6 |
+
fillCoords();
|
| 7 |
+
let shown=12,list=[];
|
| 8 |
+
function esc(s){return String(s).replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]))}
|
| 9 |
+
function render(){
|
| 10 |
+
const q=$('#q').value.toLowerCase(),f=fsel.value,c=csel.value,l=$('#lab').value;
|
| 11 |
+
list=ROWS.filter(r=>{
|
| 12 |
+
if(l==='yes'&&!r.d.length)return false; if(l==='no'&&r.d.length)return false;
|
| 13 |
+
if(c&&!r.d.some(d=>d[0]==c))return false;
|
| 14 |
+
if(f&&!r.d.some(d=>TAX[d[0]-1][2]===f))return false;
|
| 15 |
+
if(q&&!r.turns.some(t=>t[1].toLowerCase().includes(q)))return false;
|
| 16 |
+
return true});
|
| 17 |
+
$('#count').textContent=list.length+' of '+ROWS.length+' sampled rows';
|
| 18 |
+
$('#rows').innerHTML=list.slice(0,shown).map(r=>{
|
| 19 |
+
const t=r.turns.map((x,i)=>`<div class="turn ${x[0]} ${i===r.t?'t':''}"><small>Speaker ${x[0]}${i===r.t?' (target)':''}</small>${esc(x[1])}</div>`).join('');
|
| 20 |
+
const ch=r.d.length?r.d.map(d=>`<span class="chip" title="${esc(TAX[d[0]-1][3])}">${esc(TAX[d[0]-1][1])} ${d[1]}</span>`).join(''):'<span class="chip none">no expressed coordinate</span>';
|
| 21 |
+
return `<div class="dlg">${t}<div>${ch}</div><div class="meta">Labels are for speaker ${r.s}, turn ${r.t}. Hover a label for its definition.</div></div>`}).join('')||'<p class="note">No rows match.</p>';
|
| 22 |
+
$('#more').style.display=list.length>shown?'inline-block':'none';
|
| 23 |
+
}
|
| 24 |
+
['q','coord','lab'].forEach(i=>$('#'+i).addEventListener('input',()=>{shown=12;render()}));
|
| 25 |
+
fsel.addEventListener('input',()=>{fillCoords();shown=12;render()});
|
| 26 |
+
$('#more').onclick=()=>{shown+=12;render()};
|
| 27 |
+
render();
|
| 28 |
+
const fam=$('#famgrid');fams.forEach(f=>{const n=TAX.filter(t=>t[2]===f);fam.insertAdjacentHTML('beforeend',`<div><b>${esc(f)}</b><span>${n.length} coordinates, e.g. ${n.slice(0,3).map(x=>esc(x[1])).join(', ')}</span></div>`)});
|
| 29 |
+
const io=new IntersectionObserver(e=>e.forEach(x=>x.isIntersecting&&x.target.classList.add('in2')),{threshold:.08});
|
| 30 |
+
document.querySelectorAll('section').forEach(s=>{s.classList.add('fade');io.observe(s)});
|
| 31 |
+
document.querySelectorAll('.stat b[data-n]').forEach(el=>{const n=+el.dataset.n,d=el.dataset.d||'',s=el.dataset.s||'';let k=0;const id=setInterval(()=>{k+=n/30;if(k>=n){k=n;clearInterval(id)}el.textContent=(d?k.toFixed(+d):Math.round(k).toLocaleString())+s},30)});
|