const $ = document.querySelector.bind(document); const $$ = document.querySelectorAll.bind(document); function scheduleCCall(f, ms, ...args) { const func = UTF8ToString(f); return setTimeout(() => Module[`_${func}`](...args), ms); } function toCString(str) { // caller must free if (!str) return 0; const size = lengthBytesUTF8(str) + 1; const ptr = _malloc(size); stringToUTF8(str, ptr, size); return ptr; } function elemGetContent(sel) { // caller must free return toCString($(UTF8ToString(sel)).textContent); } function elemSetContent(sel, str) { $(UTF8ToString(sel)).textContent = str ? UTF8ToString(str) : ''; } function elemSetValue(sel, str) { $(UTF8ToString(sel)).value = str ? UTF8ToString(str) : ''; } function elemHasClass(sel, c) { return $(UTF8ToString(sel)).classList.contains(UTF8ToString(c)); } function elemAddClass(sel, c) { $(UTF8ToString(sel)).classList.add(UTF8ToString(c)); } function elemRemoveClass(sel, c) { $(UTF8ToString(sel)).classList.remove(UTF8ToString(c)); } function elemToggleClass(sel, c) { $(UTF8ToString(sel)).classList.toggle(UTF8ToString(c)); } function elemSetUniqClass(sel, c, sel_set) { selstr = sel && UTF8ToString(sel); cstr = UTF8ToString(c); $$(UTF8ToString(sel_set)).forEach(e => e.classList[ sel && e.matches(selstr) ? 'add' : 'remove'](cstr)); } function elemScrollToBottom(sel) { const e = $(UTF8ToString(sel)); e.scrollTop = e.scrollHeight; } function elemAppendElemv(sel, elemc, elemv, off_ns, off_name, off_content, off_n_attrs, off_attr_names, off_attr_vals) { const target = $(UTF8ToString(sel)); for (let ptr = elemv; ptr < elemv + 4*elemc; ptr += 4) { const struct = HEAP32[ptr>>2]; const nsptr = HEAP32[(struct + off_ns)>>2]; const name = UTF8ToString(HEAP32[(struct + off_name)>>2]); const e = nsptr ? document.createElementNS(UTF8ToString(nsptr), name) : document.createElement(name); const n_attrs = HEAP32[(struct + off_n_attrs)>>2]; if (n_attrs) { const attr_names = HEAP32[(struct + off_attr_names)>>2]; const attr_vals = HEAP32[(struct + off_attr_vals)>>2]; for (let i = 0; i < n_attrs; ++i) e.setAttribute( UTF8ToString( HEAP32[(attr_names + i*4)>>2]), UTF8ToString( HEAP32[(attr_vals + i*4)>>2])); } const content = HEAP32[(struct + off_content)>>2]; if (content) e.textContent = UTF8ToString(content); target.appendChild(e); } } function promptHandle(command, data) { const str_c = toCString(command); const str_d = data && toCString(data); _prompt_handle(str_c, str_d); _free(str_c); if (str_d) _free(str_d); } function readOpt(opt) { // caller must free return toCString(localStorage.getItem(UTF8ToString(opt))); } function storeOpt(opt, val) { localStorage.setItem(UTF8ToString(opt), UTF8ToString(val)); } function boatAfloat() { if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', () => _init()); else _init(); } function flipControls() { const enabled = $('#main').classList.toggle('right-controls'); $('#flip-controls-button').textContent = enabled ? '\u2190' : '\u2192'; } document.addEventListener('DOMContentLoaded', () => { let f; f = e => e.target.dataset.command.split(';').forEach(x => promptHandle(...x.split(':', 2))); $$('[data-command]').forEach(x => x.addEventListener('click', f)); f = e => _set_opt(toCString(e.target.dataset.opt), toCString(e.target.value)); $$('[data-opt]').forEach(x => x.addEventListener('change', f)); $('#flip-controls-button').addEventListener('click', flipControls); f = e => $(`#${e.target.dataset.modal}`).style.display = 'block'; $$('[data-modal]').forEach(x => x.addEventListener('click', f)); f = e => { if (e.target === e.currentTarget) e.target.style.display = 'none'; }; $$('.modal').forEach(x => x.addEventListener('click', f)); }); document.addEventListener('keydown', e => { if (e.altKey || e.ctrlKey || e.metaKey || e.target.type == 'text') return; if (isFinite(e.key)) promptHandle('append', e.key); else if (e.key == 'Enter') promptHandle('submit'); else if (e.key == 'Backspace') promptHandle('backspace'); else if (e.key == 'c') promptHandle('clear'); else if (e.key == 'r') promptHandle('rem'); else if (e.key == 'u') promptHandle('undo'); });