/* TODO document 'input-list'. ∀ children('.input-list') => 'unit' ∈ classList(child)
*/ function transferListeners(old_unit, new_unit) { for (let [o, n] of zip([old_unit, ...old_unit.querySelectorAll("*")], [new_unit, ...new_unit.querySelectorAll("*")])) { for (const key in o.listeners) { if (! o.listeners.hasOwnProperty(key)) continue; for (let proc of o.listeners[key]) { n.addEventListener(key, proc); } } } } function advance_final(input_list) { let old_unit = input_list.unit; let new_unit = old_unit.cloneNode(true); new_unit.classList.add('final'); transferListeners(old_unit, new_unit); input_list.appendChild(new_unit); } function update_inline_list () { /* can target self */ let unit = this.closest('.unit'); let lst = this.closest('.input-list'); if (unit.classList.contains("final")) { if (this.value !== '') { unit.classList.remove('final'); advance_final(lst); } } else { /* TODO all significant fields empty, instead of just current */ if (this.value === '') { let sibling = unit.previousElementSibling || unit.nextElementSibling; unit.remove(); if (sibling.tagName !== 'input') sibling = sibling.querySelector('input'); sibling.focus(); } } } /* run this from window.onload (or similar) */ function init_input_list() { for (let lst of document.getElementsByClassName('input-list')) { for (let el of lst.getElementsByTagName('input')) { el.addEventListener('input', update_inline_list); } let oldUnit = lst.querySelector('.final.unit') let unit = oldUnit.cloneNode(true); transferListeners(oldUnit, unit); lst.unit = unit; } }