JavaScript中如何自定义“确认”对话框?

48

我一直在开发一个使用自定义“模态对话框”的ASP.net项目。这里的“模态对话框”用引号括起来是因为我知道它其实只是html文档中设置为出现在其余文档“顶部”的一个div,而并不是真正意义上的模态对话框。

在网站的许多部分,我的代码看起来像这样:

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

这样做是可以的,但最好让确认对话框与页面的其他部分风格相匹配。

然而,由于它不是真正的模态对话框,我认为需要编写类似于以下内容的代码:(在此示例中,我使用jQuery-UI)

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

这是实现我想要的功能的好方法吗?还是有更好的方法?


如果你正在寻找纯JS解决方案,这篇文章可能会有所帮助: http://stackoverflow.com/q/25669026/274502 - cregox
9个回答

66

你可能想要将它抽象成一个函数,像这样:

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();
    });
}

你可以像这样使用它:

dialog('Are you sure you want to do this?',
    function() {
        // Do something
    },
    function() {
        // Do something else
    }
);

4
无论我如何做,我都必须定义自定义函数,对吗?没有办法像使用内置的 confirm 函数一样编写 if (confirm('blah?')) - Vivian River
3
将您的自定义确认函数简单地返回TRUE或FALSE如何?然后通过if(customConfirm()){ //do something} else{ //do something else}来处理它。 - Andrew Brown
5
但是函数会在什么时候返回呢?这就是关键。你正在等待用户点击某些东西。要在返回之前检测到它,您需要让函数体内的执行保持不间断,但这只能通过旋转来实现,而这是一个糟糕的想法。 - alnorth29
4
在设置“单击事件”之前,最好调用.off('click')以确保您的对话框不会同时触发多个事件。 - Ramtin
2
对于阅读此内容的任何人,按照 @Ramtin 的建议去做非常重要,否则每次点击“是”按钮都会触发多个事件。当然,我通过一种艰难的方式发现了这一点。 - Jake H
显示剩余2条评论

31

SweetAlert

如果你想要省去一些工作,可以考虑使用SweetAlert。它默认的外观就非常美观,同时也支持高度自定义。

确认示例

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()
);

示例提示


嗨,我尝试在我的ASP.NET代码中使用它,但它不会触发按钮的onClick方法。请帮忙。 http://stackoverflow.com/questions/43227386/sweet-alert-confirm-dialog-in-asp-net - Akshay

23
为了让您能够像正常的确认对话框一样使用确认框,我会使用 Promise,这将使您能够等待结果的完成并根据此采取行动,而不必使用回调函数。这将允许您按照其他代码部分中的相同模式进行操作,例如...
  const confirm = await ui.confirm('Are you sure you want to do this?');

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

请参考Codepen示例或运行下面的片段。

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

在此输入图像描述

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>


这是一个很好的答案。我还在逐渐适应 Promise,所以这对我学习很有帮助,而且自己构建 UI 总是比使用第三方库更可取。 - Millar248
很高兴你觉得它有用 :) - user3284707
太棒了!真的很喜欢这个解决方案!不知道为什么我之前没想到过 - 看起来是 Promise 的一个相当合理的用法。应该是现代浏览器首选的方式。 - dmikam
这比被接受的答案更好,因为它不需要使用回调函数。 - Philip

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>


2
我会使用jQuery UI网站上提供的示例作为模板:
$( "#modal_dialog" ).dialog({
    resizable: false,
    height:140,
    modal: true,
    buttons: {
                "Yes": function() {
                    $( this ).dialog( "close" );
                 },
                 "No": function() {
                    $( this ).dialog( "close" );
                 }
             }
});

0
面对相同的问题,我能够用纯 JS 解决它,但方式很丑陋。更准确地说,非过程式的方式。我删除了所有的函数参数和返回值,并用全局变量替换它们,现在这些函数只是包含代码行的容器 - 它们不再是逻辑单元。
在我的情况下,我还需要许多确认(由解析器处理文本)。我的解决方案是将第一个确认之前的所有内容放在一个 JS 函数中,该函数以绘制自定义弹出窗口结束,然后终止。
然后,我的弹出窗口中的按钮调用另一个函数,该函数使用答案,然后像往常一样继续工作(解析)直至下一个确认时,再次绘制屏幕,然后终止。这个第二个函数根据需要调用。
两个函数也会识别出工作完成的时间 - 它们进行一些清理,然后永久完成。结果是我完全掌控了弹出窗口;我所付出的代价是优雅性。

0
我创建了一个包含以下代码的JS文件,并将其命名为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(); 
    })    
}

在我的主PHP文件中,像这样调用JavaScript中的confirm:

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

不要忘记在head部分添加js文件。 - k suresh Nair

0
一种其他的方式是使用 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();
            });
    }});
}

这里的okHandler是什么,如何在调用时传递它? - Lokesh Sanapalli
明白了...这是一个在点击“是”时调用的函数...谢谢...对Web技术不太熟悉... - Lokesh Sanapalli

0

我找到了一种解决方案,可以让你在代码中使用默认的confirm()函数进行最少的更改。这个例子使用了jQuery和Bootstrap,但是其他库也可以实现同样的效果。你只需要复制粘贴这段代码,就可以立即使用。

<!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>

这是一个完整的示例。在您实现它之后,您将能够像这样使用它:

if ( confirm('你确定吗?',$(this)) )


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接