Custom "confirm" dialog in JavaScript?
Asked Answered
H

9

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?

Harless answered 3/8, 2011 at 15:54 Comment(1)
L
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
    }
);
Lelalelah answered 3/8, 2011 at 16:1 Comment(7)
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.Harless
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.Lelalelah
what about having your custom confirm function simply return TRUE or FALSE? then handle it by if(customConfirm()){ //do something} else{ //do something else}Manhole
@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.Lelalelah
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.Kling
For anyone reading this, It's important to do what @Kling is suggesting, otherwise each time you click the "yes" button, it will fire multiple events. Of course, I found this out the hard way.Gonzales
@Lelalelah 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 functionBaryram
P
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

Pubes answered 28/8, 2016 at 18:27 Comment(1)
Hi I tried to use it in my asp.net code but it doesn't trigger the onClick method of the button. Pls help. #43227886Addressee
Q
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>
Quip answered 16/11, 2019 at 14:51 Comment(4)
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.Lubbock
Glad you found it useful :)Quip
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.Laminitis
This is better than the accepted answer because it doesn't require the use of callbacksGaliot
W
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" );
                 }
             }
});
When answered 3/8, 2011 at 16:0 Comment(0)
P
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>
Pernod answered 16/11, 2017 at 10:27 Comment(0)
Z
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();
            });
    }});
}
Zingale answered 25/1, 2013 at 14:13 Comment(2)
what is okHandler here, and how to pass it while callingProfanatory
Got it... it's a function to call when he click on Yes... Thank you... weak in web technologies...Profanatory
B
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.

Boulware answered 22/4, 2020 at 20:3 Comment(0)
N
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)) )

Nix answered 1/12, 2020 at 14:20 Comment(0)
S
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.....")
            }
        }); 
    })
Swaggering answered 26/6, 2022 at 8:24 Comment(1)
Dont forget to add the js file in head sectionSwaggering

© 2022 - 2024 — McMap. All rights reserved.