46

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?

Vivian River
  • 31,198
  • 62
  • 198
  • 313

9 Answers9

65

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
    }
);
alnorth29
  • 3,525
  • 2
  • 34
  • 50
  • 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. – Vivian River Aug 03 '11 at 16:05
  • You could basically just spin until the user has clicked on something. The problem with that is that you stop the JS thread from doing anything else while it's waiting. You're probably better off using callback functions. – alnorth29 Aug 03 '11 at 16:07
  • 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}` – Andrew Brown Nov 09 '13 at 00: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 Nov 12 '13 at 11:48
  • 4
    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 Nov 01 '18 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 Dec 18 '20 at 02:32
  • @alnorth29 I don't understand why I get this error below. I am using dialog() in other parts of application but when I try to use your approach for reusability it breaks. I guess the difference is this time I am trying to use it from a kendoWindow. That is the only difference. Error: TypeError: $(...).dialog is not a function – Patrick95 Feb 09 '22 at 22:45
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

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • Hi I tried to use it in my asp.net code but it doesn't trigger the onClick method of the button. Pls help. http://stackoverflow.com/questions/43227386/sweet-alert-confirm-dialog-in-asp-net – Akshay Apr 05 '17 at 09:41
23

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>
user3284707
  • 3,033
  • 3
  • 35
  • 69
  • 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 Mar 31 '20 at 14:45
  • Glad you found it useful :) – user3284707 Mar 31 '20 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 Nov 11 '20 at 08:33
  • This is better than the accepted answer because it doesn't require the use of callbacks – Philip Mar 25 '21 at 10:38
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>
Alper Aydingül
  • 251
  • 1
  • 9
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" );
                 }
             }
});
James Hill
  • 60,353
  • 20
  • 145
  • 161
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();
            });
    }});
}
andro83
  • 3,563
  • 2
  • 18
  • 13
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.....")
            }
        }); 
    })