2

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.

4
  • I don't get what you want a the end : do you want to know which button have been clicked ("ok" "cancel") ? Commented Nov 17, 2014 at 14:29
  • Your code is working... what are you trying to accomplish or what specifically is not working? Also, what are you hoping to accomplish here: if (mbox("header", "msg") == true) { document.getElementById("demo").innerHTML = "Paragraph changed."; } Commented Nov 17, 2014 at 14:31
  • Yes. Basicly, i want to create a vb style messagebox function, that will return true or false value. Commented Nov 17, 2014 at 14:32
  • You should read more about event in js to understand that this is impossible that way. javascript.info/tutorial/introduction-browser-events The only way is to use callback function. Commented Nov 17, 2014 at 14:32

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

2 Comments

OK. I'm getting the hang of this. So basicly, my function is returning something that hasn't happened yet. So, we need to create a function that will be executed once the main function is ended.
That's the idea. You'd also need this if you just want to execute a couple of methods in sequence (e.g. displaying 2 of these modals), even if you do not require user input from them. Again, if you use these type of (asynchronous) methods a lot, take a look at Async or even Promises.
2

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.";
    }
});

1 Comment

It works. I'll learn more about the callback function. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.