【问题标题】:Custom "confirm" dialog in JavaScript?JavaScript中的自定义“确认”对话框?
【发布时间】:2011-10-19 06:07:09
【问题描述】:

我一直在研究一个使用自定义“模式对话框”的 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);
}

这是实现我想要的好方法,还是有更好的方法?

【问题讨论】:

标签: javascript jquery jquery-ui dialog modal-dialog


【解决方案1】:

您可能需要考虑将其抽象为这样的函数:

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

【讨论】:

  • 但是不管我怎么做,我都得定义自定义函数,对吧?没有办法像使用内置的confirm 函数那样编写if (confirm('blah?'))
  • 让您的自定义确认函数只返回 TRUE 或 FALSE 怎么样?然后由if(customConfirm()){ //do something} else{ //do something else} 处理
  • @AndrewBrown 但是函数什么时候返回?这才是重点。您正在等待用户单击某些内容。要在返回之前检测到这一点,您需要在函数体中继续执行,而这只能通过旋转来实现,这是一个糟糕的主意。
  • 最好在设置on click 事件之前调用.off('click'),以确保您的对话框不会同时触发多个事件。
  • 对于阅读本文的任何人,按照@Ramtin 的建议去做很重要,否则每次单击“是”按钮时,它都会触发多个事件。当然,我很难找到这一点。
【解决方案2】:

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

【讨论】:

【解决方案3】:

为了使您能够像正常的确认对话框一样使用确认框,我将使用 Promises,这将使您能够等待结果的结果然后对此采取行动,而不必使用回调。

这将允许您遵循与代码其他部分相同的模式,例如...

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

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

例如查看codepen,或者运行下面的sn-p。

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 总是比使用第三方库更可取。
  • 很高兴你发现它很有用:)
  • 绝招!!!真的很喜欢这个解决方案!真的不知道这怎么没有发生在我身上——看起来很合乎逻辑地使用了 Promise。应该是现代浏览器的首选方式。
  • 这比接受的答案要好,因为它不需要使用回调
【解决方案4】:

我会使用 jQuery UI 网站上给出的示例作为模板:

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

【讨论】:

    【解决方案5】:

    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>

    【讨论】:

      【解决方案6】:

      另一种方法是使用颜色框

      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是什么,调用的时候怎么传
      • 知道了...当他点击是时调用它...谢谢...网络技术薄弱...
      【解决方案7】:

      面对同样的问题,我只能使用 vanilla JS 来解决它,但方式很丑陋。更准确地说,以非程序方式。我删除了所有函数参数和返回值并用全局变量替换它们,现在这些函数仅用作代码行的容器 - 它们不再是逻辑单元。

      在我的例子中,我还遇到了需要多次确认的额外复杂性(因为解析器通过文本工作)。我的解决方案是将所有内容放在 JS 函数中进行第一次确认,最后在屏幕上绘制我的自定义弹出窗口,然后终止。

      然后我的弹出窗口中的按钮调用另一个函数,该函数使用答案,然后像往常一样继续工作(解析)直到下一次确认,当它再次绘制屏幕然后终止时。第二个函数会根据需要经常调用。

      这两个函数还可以识别工作何时完成 - 它们会进行一些清理,然后永久完成。结果是我完全控制了弹出窗口;我付出的代价是优雅。

      【讨论】:

        【解决方案8】:

        如果您在整个代码中有很多confirm() 操作,我设法找到了一个解决方案,该解决方案允许您使用默认的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('Are you sure?',$(this)))

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-14
          • 2012-06-05
          • 2010-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多