49

I've been working on an ASP.net project that uses custom 'modal dialogs'. I use scare quotes here because I understand that the 'modal dialog' is simply a div in my html document that is set to appear "on top" of the rest of the document and is not a modal dialog in the true sense of the word.

In many parts of the web site, I have code that looks like this:

var warning = 'Are you sure you want to do this?';
if (confirm(warning)) {
    // Do something
}
else {
    // Do something else
}

This is okay, but it would be nice to make the confirm dialog match the style of the rest of the page.

However, since it is not a true modal dialog, I think that I need to write something like this: (I use jQuery-UI in this example)

<div id='modal_dialog'>
    <div class='title'>
    </div>
    <input type='button' value='yes' id='btnYes' />
    <input type='button' value='no' id='btnNo' />
</div>

<script>
function DoSomethingDangerous() {
    var warning = 'Are you sure you want to do this?';
    $('.title').html(warning);
    var dialog = $('#modal_dialog').dialog();
    function Yes() {
        dialog.dialog('close');
        // Do something
    }   
    function No() {
        dialog.dialog('close');
        // Do something else
    }    
    $('#btnYes').click(Yes);
    $('#btnNo').click(No);
}

Is this a good way to accomplish what I want, or is there a better way?

1

9 Answers 9

68

You might want to consider abstracting it out into a function like this:

function dialog(message, yesCallback, noCallback) {
    $('.title').html(message);
    var dialog = $('#modal_dialog').dialog();

    $('#btnYes').click(function() {
        dialog.dialog('close');
        yesCallback();
    });
    $('#btnNo').click(function() {
        dialog.dialog('close');
        noCallback();
    });
}

You can then use it like this:

dialog('Are you sure you want to do this?',
    function() {
        // Do something
    },
    function() {
        // Do something else
    }
);
7
  • 4
    But no matter how I do it, I will have to define custom functions, right? There is no way to be able to write if (confirm('blah?')) like with the built-in confirm function. Commented Aug 3, 2011 at 16:05
  • 3
    what about having your custom confirm function simply return TRUE or FALSE? then handle it by if(customConfirm()){ //do something} else{ //do something else} Commented Nov 9, 2013 at 0:43
  • 5
    @AndrewBrown But when would the function return? That's the point. You're waiting for the user to click something. To detect that before returning you'd need to keep execution in the body of your function, which you could only do by spinning, and that's a terrible idea.
    – alnorth29
    Commented Nov 12, 2013 at 11:48
  • 5
    It would be a good practice to call .off('click') before setting the on click event to make sure that your dialog does not fire multiple events at the same time.
    – Ramtin
    Commented Nov 1, 2018 at 11:29
  • 2
    For anyone reading this, It's important to do what @Ramtin is suggesting, otherwise each time you click the "yes" button, it will fire multiple events. Of course, I found this out the hard way.
    – Jake H
    Commented Dec 18, 2020 at 2:32
31

SweetAlert

You should take a look at SweetAlert as an option to save some work. It's beautiful from the default state and is highly customizable.

Confirm Example

sweetAlert(
  {
    title: "Are you sure?",
    text: "You will not be able to recover this imaginary file!",
    type: "warning",   
    showCancelButton: true,   
    confirmButtonColor: "#DD6B55",
    confirmButtonText: "Yes, delete it!"
  }, 
  deleteIt()
);

Sample Alert

1
25

To enable you to use the confirm box like the normal confirm dialog, I would use Promises which will enable you to await on the result of the outcome and then act on this, rather than having to use callbacks.

This will allow you to follow the same pattern you have in other parts of your code with code such as...

  const confirm = await ui.confirm('Are you sure you want to do this?');

  if(confirm){
    alert('yes clicked');
  } else{
    alert('no clicked');
  }

See codepen for example, or run the snippet below.

https://codepen.io/larnott/pen/rNNQoNp

enter image description here

const ui = {
  confirm: async (message) => createConfirm(message)
}

const createConfirm = (message) => {
  return new Promise((complete, failed)=>{
    $('#confirmMessage').text(message)

    $('#confirmYes').off('click');
    $('#confirmNo').off('click');
    
    $('#confirmYes').on('click', ()=> { $('.confirm').hide(); complete(true); });
    $('#confirmNo').on('click', ()=> { $('.confirm').hide(); complete(false); });
    
    $('.confirm').show();
  });
}
                     
const saveForm = async () => {
  const confirm = await ui.confirm('Are you sure you want to do this?');
  
  if(confirm){
    alert('yes clicked');
  } else{
    alert('no clicked');
  }
}
body {
  margin: 0px;
  font-family: "Arial";
}

.example {
  padding: 20px;
}

input[type=button] {
  padding: 5px 10px;
  margin: 10px 5px;
  border-radius: 5px;
  cursor: pointer;
  background: #ddd;
  border: 1px solid #ccc;
}
input[type=button]:hover {
  background: #ccc;
}

.confirm {
  display: none;
}
.confirm > div:first-of-type {
  position: fixed;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  top: 0px;
  left: 0px;
}
.confirm > div:last-of-type {
  padding: 10px 20px;
  background: white;
  position: absolute;
  width: auto;
  height: auto;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 5px;
  border: 1px solid #333;
}
.confirm > div:last-of-type div:first-of-type {
  min-width: 150px;
  padding: 10px;
}
.confirm > div:last-of-type div:last-of-type {
  text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="example">
  <input type="button" onclick="saveForm()" value="Save" />
</div>

<!-- Hidden confirm markup somewhere at the bottom of page -->

<div class="confirm">
  <div></div>
  <div>
    <div id="confirmMessage"></div>
    <div>
      <input id="confirmYes" type="button" value="Yes" />
      <input id="confirmNo" type="button" value="No" />
    </div>
  </div>
</div>

4
  • 1
    This is a great answer. I am still getting used to promises, so this helps me learn that, plus building your own UI is always preferable to using third party libraries.
    – Millar248
    Commented Mar 31, 2020 at 14:45
  • Glad you found it useful :) Commented Mar 31, 2020 at 14:47
  • Great trick!!! Really love this solution! Don't really know how this didn't happen to me - looks like pretty logick use of promises. Should be the preferred way for modern browsers.
    – dmikam
    Commented Nov 11, 2020 at 8:33
  • 1
    This is better than the accepted answer because it doesn't require the use of callbacks
    – Philip
    Commented Mar 25, 2021 at 10:38
2

I would use the example given on jQuery UI's site as a template:

$( "#modal_dialog" ).dialog({
    resizable: false,
    height:140,
    modal: true,
    buttons: {
                "Yes": function() {
                    $( this ).dialog( "close" );
                 },
                 "No": function() {
                    $( this ).dialog( "close" );
                 }
             }
});
0
2

var confirmBox = '<div class="modal fade confirm-modal">' +
    '<div class="modal-dialog modal-sm" role="document">' +
    '<div class="modal-content">' +
    '<button type="button" class="close m-4 c-pointer" data-dismiss="modal" aria-label="Close">' +
    '<span aria-hidden="true">&times;</span>' +
    '</button>' +
    '<div class="modal-body pb-5"></div>' +
    '<div class="modal-footer pt-3 pb-3">' +
    '<a href="#" class="btn btn-primary yesBtn btn-sm">OK</a>' +
    '<button type="button" class="btn btn-secondary abortBtn btn-sm" data-dismiss="modal">Abbrechen</button>' +
    '</div>' +
    '</div>' +
    '</div>' +
    '</div>';

var dialog = function(el, text, trueCallback, abortCallback) {

    el.click(function(e) {

        var thisConfirm = $(confirmBox).clone();

        thisConfirm.find('.modal-body').text(text);

        e.preventDefault();
        $('body').append(thisConfirm);
        $(thisConfirm).modal('show');

        if (abortCallback) {
            $(thisConfirm).find('.abortBtn').click(function(e) {
                e.preventDefault();
                abortCallback();
                $(thisConfirm).modal('hide');
            });
        }

        if (trueCallback) {
            $(thisConfirm).find('.yesBtn').click(function(e) {
                e.preventDefault();
                trueCallback();
                $(thisConfirm).modal('hide');
            });
        } else {

            if (el.prop('nodeName') == 'A') {
                $(thisConfirm).find('.yesBtn').attr('href', el.attr('href'));
            }

            if (el.attr('type') == 'submit') {
                $(thisConfirm).find('.yesBtn').click(function(e) {
                    e.preventDefault();
                    el.off().click();
                });
            }
        }

        $(thisConfirm).on('hidden.bs.modal', function(e) {
            $(this).remove();
        });

    });
}

// custom confirm
$(function() {
    $('[data-confirm]').each(function() {
        dialog($(this), $(this).attr('data-confirm'));
    });

    dialog($('#customCallback'), "dialog with custom callback", function() {

        alert("hi there");

    });

});
.test {
  display:block;
  padding: 5p 10px;
  background:orange;
  color:white;
  border-radius:4px;
  margin:0;
  border:0;
  width:150px;
  text-align:center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>


example 1
<a class="test" href="http://example" data-confirm="do you want really leave the website?">leave website</a><br><br>


example 2
<form action="">
<button class="test" type="submit" data-confirm="send form to delete some files?">delete some files</button>
</form><br><br>

example 3
<span class="test"  id="customCallback">with callback</span>

0

One other way would be using colorbox

function createConfirm(message, okHandler) {
    var confirm = '<p id="confirmMessage">'+message+'</p><div class="clearfix dropbig">'+
            '<input type="button" id="confirmYes" class="alignleft ui-button ui-widget ui-state-default" value="Yes" />' +
            '<input type="button" id="confirmNo" class="ui-button ui-widget ui-state-default" value="No" /></div>';

    $.fn.colorbox({html:confirm, 
        onComplete: function(){
            $("#confirmYes").click(function(){
                okHandler();
                $.fn.colorbox.close();
            });
            $("#confirmNo").click(function(){
                $.fn.colorbox.close();
            });
    }});
}
2
  • what is okHandler here, and how to pass it while calling Commented Aug 18, 2016 at 8:26
  • Got it... it's a function to call when he click on Yes... Thank you... weak in web technologies... Commented Aug 18, 2016 at 8:46
0

Faced with the same problem, I was able to solve it using only vanilla JS, but in an ugly way. To be more accurate, in a non-procedural way. I removed all my function parameters and return values and replaced them with global variables, and now the functions only serve as containers for lines of code - they're no longer logical units.

In my case, I also had the added complication of needing many confirmations (as a parser works through a text). My solution was to put everything up to the first confirmation in a JS function that ends by painting my custom popup on the screen, and then terminating.

Then the buttons in my popup call another function that uses the answer and then continues working (parsing) as usual up to the next confirmation, when it again paints the screen and then terminates. This second function is called as often as needed.

Both functions also recognize when the work is done - they do a little cleanup and then finish for good. The result is that I have complete control of the popups; the price I paid is in elegance.

0

I managed to find the solution that will allow you to do this using default confirm() with minimum of changes if you have a lot of confirm() actions through out you code. This example uses jQuery and Bootstrap but the same thing can be accomplished using other libraries as well. You can just copy paste this and it should work right away

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Project Title</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

    <!--[if lt IE 9]>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
        <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<div class="container">
    <h1>Custom Confirm</h1>
    <button id="action"> Action </button> 
    <button class='another-one'> Another </button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>

<script type="text/javascript">

    document.body.innerHTML += `<div class="modal fade"  style="top:20vh" id="customDialog" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
    <div class="modal-content">
    <div class="modal-header">
    <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
    <span aria-hidden="true">&times;</span>
    </button>
    </div>
    <div class="modal-body">

    </div>
    <div class="modal-footer">
    <button type="button" id='dialog-cancel' class="btn btn-secondary">Cancel</button>
    <button type="button" id='dialog-ok' class="btn btn-primary">Ok</button>
    </div>
    </div>
    </div>
    </div>`;

    function showModal(text) {

        $('#customDialog .modal-body').html(text);
        $('#customDialog').modal('show');

    }

    function startInterval(element) {

         interval = setInterval(function(){

           if ( window.isConfirmed != null ) {

              window.confirm = function() {

                  return window.isConfirmed;
              }

              elConfrimInit.trigger('click');

              clearInterval(interval);
              window.isConfirmed = null;
              window.confirm = function(text) {
                showModal(text);
                startInterval();
            }

           }

        }, 500);

    }

    window.isConfirmed = null;
    window.confirm = function(text,elem = null) {
        elConfrimInit = elem;
        showModal(text);
        startInterval();
    }

    $(document).on('click','#dialog-ok', function(){

        isConfirmed = true;
        $('#customDialog').modal('hide');

    });

    $(document).on('click','#dialog-cancel', function(){

        isConfirmed = false;
        $('#customDialog').modal('hide');

   });

   $('#action').on('click', function(e) {

 

        if ( confirm('Are you sure?',$(this)) ) {

            alert('confrmed');
        }
        else {
            alert('not confimed');
        }
    });

    $('.another-one').on('click', function(e) {


        if ( confirm('Are really, really, really sure ? you sure?',$(this)) ) {

            alert('confirmed');
        }
        else {
            alert('not confimed');
        }
    });


</script>
</body>
</html>

This is the whole example. After you implement it you will be able to use it like this:

if ( confirm('Are you sure?',$(this)) )

0

I created a js file with below given code and named it newconfirm.js

function confirm(q,yes){
    var elem='<div class="modal fade" id="confirmmodal" role="dialog" style="z-index: 1500;">';
    elem+='<div class="modal-dialog" style="width: 25vw;">';      
    elem+='<div class="modal-content">';
    elem+='<div class="modal-header" style="padding:8px;background-color:lavender;">';
    elem+='<button type="button" class="close" data-dismiss="modal">&times;</button>';
    elem+='<h3 class="modal-title" style="color:black;">Message</h3></div>';        
    elem+='<div class="modal-body col-xs-12" style="padding:;background-color: ghostwhite;height:auto;">';
    elem+='<div class="col-xs-3 pull-left" style="margin-top: 0px;">';
    elem+='<img class="img-rounded" src="msgimage.jpg" style="width: 49%;object-fit: contain;" /></div><div class="col-xs-9 pull-left "><p class="aconfdiv"></p></div></div>';
    elem+='<div class="modal-footer col-xs-12" style="padding:6px;background-color:lavender;"><div class="btn btn-sm btn-success yes pull-left">Yes</div><button type="button" class="btn btn-default btn-sm" data-dismiss="modal">No</button></div></div></div></div>';
    $('body').append(elem); 
    //$('body').append('<div class="lead cresp"></div>');   
    $('.aconfdiv').html(q);
    $('#confirmmodal').modal('show');
    $('.yes').on('click',function(){        
        //$('body').find('.cresp').html('Yes');
        localStorage.setItem("cresp","Yes");
        $('#confirmmodal').modal('hide');  
        yes(); 
    })    
}

and in my main php file calling confirm in the javascript like this

$('.cnf').off().on('click',function(){
        confirm("Do you want to save the data to Database?<br />Kindly check the data properly as You cannot undo this action",function(){
            var resp=localStorage.getItem("cresp");
            localStorage.removeItem("cresp");
            //$('body').find('.cresp').remove();
            if(resp=='Yes'){
                alert("You clicked on Yes Bro.....")
            }
        }); 
    })
1
  • Dont forget to add the js file in head section Commented Jun 26, 2022 at 8:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.