I have the following code:
if(changedStatus()){
var mAns = confirm("You have changed your status. This will alter your estate plan and may cause you to lose some data. Are you sure that you want to do this?");
if(!mAns) return false;
}
This works great with the default JS confirm pop-up, but I would like to implement the same action with HTML5 buttons instead:
<div id="cres_statusmssg">
<p>Changing your status will alter your estate plan and may cause you to lose some data. Do you want to proceed?</p>
<button id="cres_yes">Yes</button>
<button id="cres_cancel">Cancel</button>
I have applied click events to both buttons, but I can't get them to work. Any ideas?
CodePudding user response:
You'll need to understand how to write for asynchrony, since there is no other way to achieve what you want to do. The built-in confirm
(and prompt
, alert
etc) effectively pause JS execution until the user has interacted with the pop-up
Writing nicer pop-ups, you don't have that luxury. You'll need to use callbacks to achieve a working solution
I'd recommend using Promises - which are just glorified callbacks anyway, with the added advantage of being able to be used with async
/await
- this has the advantage of making the code look more like the code you're used to if you haven't done much asynchronous coding
function statusmssgDialog() {
const dlg = document.getElementById('cres_statusmssg');
dlg.showModal();
return new Promise((resolve, reject) => {
const clk = function(e) {
resolve(this.dataset.value === 'true');
dlg.close();
};
dlg.querySelectorAll('button').forEach(btn =>
btn.addEventListener('click', clk, { once: true})
);
});
}
// usage - it's easier if the function where you
// call statusmssgDialog is `async`
// but you can also use Promise.then/.catch of course
//
async function fn() {
if( true /*changedStatus()*/){
const mAns = await statusmssgDialog();
console.log(`user action is ${mAns}`);
if(!mAns) return mAns;
}
console.log('doing more things here when yes is clicked or chengedStatus is false?');
}
// asynchrony is like a virus,
// anything that calls an asynchronous function and needs the result
// needs to be written to account for asynchrony
// here, I use .then/.catch instead of async/await
// because await isn't an option at the top-level of code
// unless it's the top-level of a module script in modern browsers
fn().then(r => {
if (r === false) {
console.log('cancel was clicked');
return;
}
console.log('yes was clicked');
});
.modal-dialog {
border-radius: 9px;
box-shadow: 0 0 1em rgb(127 127 127 / 0.8);
width: 30rem;
max-width: 90%;
}
.modal-dialog::backdrop {
background: rgb(0 0 0 / 0.4);
backdrop-filter: blur(1px);
}
body {
background-color: hsl(240 100% 95%);
}
<dialog id="cres_statusmssg" >
<div>
<p>Changing your status will alter your estate plan and may cause you to lose some data. Do you want to proceed?</p>
<button id="cres_yes" data-value="true">Yes</button>
<button id="cres_cancel" data-value="false">Cancel</button>
</div>
</dialog>
<div>
<p>Dummy page text</p>
<div>
In the above, the dialog promise always resolves, but there is an alternative, to reject if cancel is pressed
function statusmssgDialog() {
const dlg = document.getElementById('cres_statusmssg');
dlg.showModal();
return new Promise((resolve, reject) => {
const clk = function(e) {
dlg.close();
if (this.dataset.value !== 'true') {
return reject('cancel pressed');
}
resolve('yes pressed');
};
dlg.querySelectorAll('button').forEach(btn =>
btn.addEventListener('click', clk, { once: true})
);
});
}
async function fn() {
if( true /*changedStatus()*/) {
try {
const mAns = await statusmssgDialog();
console.log(`yes pressed`);
} catch(e) {
console.log('cancel was pressed');
throw e; // pass the cancel "error" to the caller
}
}
console.log('doing more things here when yes is clicked or chengedStatus is false?');
}
fn().then(r => {
console.log('yes was clicked');
}).catch(e => {
console.log(`user action was ${e}`);
});
.modal-dialog {
border-radius: 9px;
box-shadow: 0 0 1em rgb(127 127 127 / 0.8);
width: 30rem;
max-width: 90%;
}
.modal-dialog::backdrop {
background: rgb(0 0 0 / 0.4);
backdrop-filter: blur(1px);
}
body {
background-color: hsl(240 100% 95%);
}
<dialog id="cres_statusmssg" >
<div>
<p>Changing your status will alter your estate plan and may cause you to lose some data. Do you want to proceed?</p>
<button id="cres_yes" data-value="true">Yes</button>
<button id="cres_cancel" data-value="false">Cancel</button>
</div>
</dialog>
<div>
<p>Dummy page text</p>
<div>
CodePudding user response:
Try to use Bootstrap Modal
Using Twitter bootstrap modal instead of confirm dialog
Or jquery ui