9

I would like to create a JavaScript function similar to confirm() that shows a dialog (a div with a question and 2 buttons) and returns true if the user clicks "Ok" or false otherwise.

Is it possible to do that using JavaScript/jQuery but without plugins (e.g. jQuery UI or Dialog)? Because I'm trying to reduce size and round trip times...

I tried to write this code, but I don't know how to make the function "wait" for the user click.

I would like to use my function in this way:

answer=myConfirm("Are you sure?")

In this way I could use the same function in several contexts, simply changing the question passed as a parameter. This is the same behavior of confirm()

Don't Panic
  • 41,125
  • 10
  • 61
  • 80
supergiox
  • 1,586
  • 7
  • 19
  • 27
  • 1
    Possibly of interest: [`window.showModalDialog()`](https://developer.mozilla.org/en/DOM/window.showModalDialog). – David Thomas May 30 '12 at 22:14
  • You really have to implement a custom confirmation dialog with a callback. You display the dialog, and the callback function gets called once the user clicks a button. – Sam Dufel May 30 '12 at 22:15
  • The click event on the "yes" and "no" buttons has to be re-bound/re-defined for each instance of the popup. If you only define them once there is no way for the click event to return the boolean value to the most recent instance. That's the purpose of a callback, to give the "yes/no" buttons a context within which to act. – Brad Barrow May 31 '12 at 04:44

3 Answers3

14

Rather than waiting for the user's input and then returning from the function, it is more common in JavaScript to provide a callback function that will be called when the action you're waiting for is complete. For example:

myCustomConfirm("Are you sure?", function (confirmed) {
    if (confirmed) {
        // Whatever you need to do if they clicked confirm
    } else {
        // Whatever you need to do if they clicked cancel
    }
});

This could be implemented along the lines of:

function myCustomConfirm(message, callback) {
    var confirmButton, cancelButton;

    // Create user interface, display message, etc.

    confirmButton.onclick = function() { callback(true); };
    cancelButton.onclick = function() { callback(false); };
}
georgebrock
  • 28,393
  • 13
  • 77
  • 72
  • @supergiox: You can still use the function I described in different contexts. The only difference is instead of writing `if (myConfirm(msg)) { … } else { … }` each time you use it, you write `myConfirm(msg, function (c) { if (c) { … } else { … } });` – georgebrock May 31 '12 at 05:28
  • thanks, it works. we can even create a function to display more buttons. use 0 and 1 as false and true by default and other numbers for different options. – Victor Ferreira Dec 04 '13 at 19:53
2

If using jQuery, why not implement jQueryUI? And use the Dialog function as follows:

as a 2 part:

HTML

<div id="dialog-confirm" title="ALERT">
    <p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>Are you sure?</p>
</div>

Script

$( "#dialog-confirm" ).dialog({
    resizable: false,
    modal: true,
    buttons: {
        "OK": function() {
            $( this ).dialog( "close" );
        },
        Cancel: function() {
            $( this ).dialog( "close" );
        }
    }
});

All in Script:

$(function() {
    $("<div />").attr("id", "dialog-confirm").append(
        $("<p />").text('Are you sure?').css("text-align", "center").prepend(
            $("<span />").addClass("ui-icon ui-icon-alert").css({
                float: 'left',
                margin: '0 7px 20px 0'
            })
        )
    ).dialog({
        resizable: false,
        modal: true,
        title: "ALERT",
        buttons: {
            "OK": function() {
                answer=1;
                $(this).dialog("close");
            },
            "Cancel": function() {
                answer=0;
                $(this).dialog("close");
            }
        }
    });
});

jsFiddle

SpYk3HH
  • 22,272
  • 11
  • 70
  • 81
  • I want to save as much space as possible. If there isn't a "pure" javascript way I'll use your solution – supergiox May 30 '12 at 23:01
  • 2
    You're using jquery but you want "pure javascript" ... that just doesn't make since? If it's a memory thing, jqueryui is a very lightweight extension to jquery, but if its a server memory thing, well ... its still a very small minified file. – SpYk3HH May 30 '12 at 23:04
1

This really should be done with a callback. The closest thing to what you're after would be to use a publish and subscribe model with some custom events.

To do so:

When a user clicks the yes button, trigger a custom event called clickedYes. Do the same for "no"

$('#yesbtn').click(function(){
    $(document).trigger('clickedYes');
});

$('#nobtn').click(function(){
    $(document).trigger('clickedNo');
});

Now we need to "listen" or subscribe for those events and execute the appropriate action in context.

Lets create a hypothetical situation: Your user clicks delete and you want to confirm that choice.

First setup what you want to happen if they click yes:

$(document).unbind('clickedYes'); //Unbind any old actions
$(document).bind('clickedYes',function(){
    //Code to delete the item
    //Hide the popup
});

then what you want to happen if they click no:

$(document).unbind('clickedNo'); //Unbind any old actions
$(document).bind('clickedNo',function(){
    //Hide the popup and don't delete
});

So we've setup actions that are listening for clickedYes or clickedNo. Now we just need to show the user the popup so that they have to click yes or no. When they do, they'll trigger the events above.

so your myConfirm() function will just do the following:

function myConfirm(msg){
    //change the message to 'msg'
    //Show the popup
}

So the order would be:

  1. Bind triggers for the custom events to the yes and no buttons
  2. Before prompting - unbind any old actions and attach your new ones
  3. Present the user with a popup that'll cause them to trigger on of your actions.

This will allow you to call the function like this myConfirm('Are you sure'); It's not quite what you're after...but I don't think it's possible to do exactly what you want.

Brad Barrow
  • 1,036
  • 10
  • 18