Member area: in-page dialogs replace every browser prompt/confirm
Mobile Safari shows a red 'Suppress dialogs' option on the second native pop-up in a row and, once tapped, swallows every later prompt on the site until reload (Hugh, 2026-09-12, campaign top-up). IAP.ask / IAP.confirmBox in common.js render a modal-card dialog (Enter/Escape, focus, backdrop cancel); all nine call sites in my.js use them (top-up credits, link insert x2 with selection restore, pay it forward, adopt note, release, unlink, add position, Trust Wallet check). Version tags bumped on every page that loads common.js. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+28
-1
@@ -205,5 +205,32 @@ window.IAP = (function () {
|
||||
note: 'Joined through you so far: <b>' + refs + '</b>.' }
|
||||
];
|
||||
}
|
||||
return { getConfig, fmtPol, fmtUsd, status, renderNav, refreshNavWallet, describeEvent, feedRow, adSlot, reportAd, requestCode, launchChecks, launchToggle, $ };
|
||||
// In-page dialogs instead of window.prompt / confirm. Mobile Safari shows a red "Suppress dialogs"
|
||||
// option on the second native pop-up in a row and, once tapped, swallows every later prompt on the
|
||||
// site until reload. ask() resolves the typed value (null on cancel); confirmBox() resolves true/false.
|
||||
function dialog(o) {
|
||||
return new Promise(resolve => {
|
||||
const esc = t => String(t == null ? '' : t).replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]));
|
||||
const back = document.createElement('div'); back.className = 'modal-back'; back.style.zIndex = '200';
|
||||
const field = o.type === 'none' ? '' : o.type === 'textarea'
|
||||
? '<textarea id="dlgInput" rows="5" style="width:100%;margin-top:12px">' + esc(o.value) + '</textarea>'
|
||||
: '<input id="dlgInput" type="' + (o.type === 'number' ? 'number' : 'text') + '" ' + (o.type === 'number' ? 'inputmode="decimal" min="0" step="any" ' : '') + 'value="' + esc(o.value) + '" placeholder="' + esc(o.placeholder) + '" style="width:100%;margin-top:12px" autocomplete="off">';
|
||||
back.innerHTML = '<div class="modal-card" role="dialog" aria-modal="true">' + (o.title ? '<h3 style="margin:0 0 8px">' + esc(o.title) + '</h3>' : '')
|
||||
+ (o.text ? '<p class="muted small" style="margin:0;white-space:pre-line">' + esc(o.text) + '</p>' : '') + field
|
||||
+ '<div style="display:flex;gap:10px;justify-content:flex-end;margin-top:16px;flex-wrap:wrap"><button type="button" class="btn ghost" id="dlgCancel">' + esc(o.cancel || 'Cancel') + '</button><button type="button" class="btn" id="dlgOk">' + esc(o.ok || 'OK') + '</button></div></div>';
|
||||
document.body.appendChild(back);
|
||||
const inp = back.querySelector('#dlgInput');
|
||||
const done = v => { document.removeEventListener('keydown', onKey); back.remove(); resolve(v); };
|
||||
const okv = () => done(o.type === 'none' ? true : (inp ? inp.value : ''));
|
||||
const onKey = e => { if (e.key === 'Escape') { e.preventDefault(); done(o.type === 'none' ? false : null); } else if (e.key === 'Enter' && o.type !== 'textarea') { e.preventDefault(); okv(); } };
|
||||
document.addEventListener('keydown', onKey);
|
||||
back.querySelector('#dlgOk').addEventListener('click', okv);
|
||||
back.querySelector('#dlgCancel').addEventListener('click', () => done(o.type === 'none' ? false : null));
|
||||
back.addEventListener('click', e => { if (e.target === back) done(o.type === 'none' ? false : null); });
|
||||
setTimeout(() => { if (inp) { inp.focus(); if (inp.select && o.type !== 'textarea') inp.select(); } else back.querySelector('#dlgOk').focus(); }, 30);
|
||||
});
|
||||
}
|
||||
function ask(o) { return dialog(Object.assign({ type: 'text', value: '', placeholder: '' }, o || {})); }
|
||||
function confirmBox(text, o) { return dialog(Object.assign({ type: 'none', text, ok: 'Yes', cancel: 'No' }, o || {})); }
|
||||
return { getConfig, fmtPol, fmtUsd, status, renderNav, refreshNavWallet, describeEvent, feedRow, adSlot, reportAd, requestCode, launchChecks, launchToggle, ask, confirmBox, $ };
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user