Reputation: 33
I'm trying to create a stylized yes/no dialog that can be called (created and destroyed) by single java script function, that will return a value depending on which button is clicked. But the function only return the declared value, not the one that is depending by the button clicked. Here's the core of the code:
<script>
function mbox(header, msg) {
var result = false;
var modal = document.createElement("div");
var modal_ok = document.createElement("input");
var modal_cancel = document.createElement("input");
modal.id = "modal";
modal_ok.id = "modal_ok";
modal_ok.type = "submit";
modal_ok.value = "OK";
modal_ok.onclick = function(){clicked(1)};
modal_cancel.id = "modal_cancel";
modal_cancel.type = "submit";
modal_cancel.value = "Cancel";
modal_cancel.onclick = function(){clicked(0)};
modal.appendChild(modal_ok);
modal.appendChild(modal_cancel);
document.body.appendChild(modal);
document.getElementById('modal_ok').focus();
function clicked(param){
if(param == 1){
result = true;
}else{
result = false;}
var elem = document.getElementById("modal");
elem.parentNode.removeChild(elem);
}
return result;
}
</script>
<p id="demo">My First Paragraph.</p>
<script>
if(mbox("header", "msg") == true){document.getElementById("demo").innerHTML = "Paragraph changed.";}
</script>
Please, no jquery or any other instant framework solutions. I'm still learning javascript, so I want to understand the concept.
Thanks in advance for any help, and sorry for my english.
Upvotes: 2
Views: 256
Reputation: 938
The problem is that showing the dialog (and getting the user input from it) is an asynchronous action (i.e. it does not yield a result right away), and that you are trying to use it synchronously (comparing the return type at the same moment you call the function).
When the mbox() method reaches the return result
, the user has not clicked on either OK or Cancel yet.
A way to fix this is by using a callback pattern. You define a function to be executed after the mbox is closed, and pass it to mbox() like this:
<script>
mbox("header", "msg", function (result){
if (result) {
document.getElementById("demo").innerHTML = "Paragraph changed.";
}
});
</script>
Then modify the clicked() method to call the defined callback with the result:
function clicked(param) {
if(param == 1) {
result = true;
} else {
result = false;
}
var elem = document.getElementById("modal");
elem.parentNode.removeChild(elem);
callback(result); // or even shorter: callback(param == 1)
}
Don't forget to update the mbox() method to accept a third (callback) parameter, and you can basically remove the return statement at the end of the function body.
Finally, if you're going to work with a lot of asynchronous functions, you might want to check out other solutions for result handling, such as Promises, as callbacks in callbacks in callbacks are sometimes difficult to handle properly (especially when the async operations might fail/return an error).
Upvotes: 2
Reputation: 16837
You can't return a value in the mbox function because you are waiting for a user to interact. You should use a callback to the messagebox like so:
function mbox(header, msg, callback) {
And your click function looks something like this:
function clicked(param){
callback && callback(param === 1);
modal.parentNode.removeChild(modal);
}
And now you can call it like so:
mbox('Confirm','Please tell me you like this answer', function(bool){
if(bool){
document.getElementById("demo").innerHTML = "Paragraph changed.";
}
});
Upvotes: 2