【问题标题】:How do I know which button is clicked when the bootstrap modal closes?当引导模式关闭时,我如何知道单击了哪个按钮?
【发布时间】:2015-03-31 23:05:06
【问题描述】:

这是我的模态 html 代码:

<div class="modal fade" id="delete-file-modal" role="dialog">
    <div class="modal-dialog">
        <div class="modal-content">
            <form class="form-horizontal" method="post" id="delete_file_form">

                <div class="modal-body">
                    Are you sure you want to delete this file?  
                </div>  

                <div class="modal-footer">
                    <button data-dismiss="modal" class="btn btn-danger" name="in_confirm_insert" id="confirm-delete-button">Delete</button>
                    <button data-dismiss="modal" class="btn btn-default" name="in_confirm_insert" id="cancel-delete-button">Cancel</button>
                </div>

            </form>
        </div>
    </div>
</div>

这是我的 javascript 代码:

$('#delete-file-modal').on('hidden.bs.modal', function (e) {

    var delete_button = $(e.target).is("#confirm-delete-button");

    if(delete_button === true) {
        //delete file
        alert("file deleted.");
    } else {
        alert("delete failed.");
    };
});

我需要能够检查删除文件模式关闭时是否单击了删除按钮。我的 javascript 代码中是否还缺少其他内容?

【问题讨论】:

    标签: javascript jquery html twitter-bootstrap


    【解决方案1】:

    选项 #1

    hidden.bs.modal 事件监听器中,event.target 指的是被隐藏的模态元素,不是触发事件的点击元素。

    如果您想确定哪个按钮触发模态关闭,一种选择是将事件侦听器添加到模态内的按钮元素。然后在按钮事件侦听器内部,您可以侦听父 #modal 元素上的 hidden.bs.modal 事件,以确定模式是否已关闭。由于hidden.bs.modal 事件侦听器位于按钮click 事件侦听器内,因此您仍然拥有对触发click 事件的元素的引用。

    Example Here

    $('#delete-file-modal .modal-footer button').on('click', function(event) {
      var $button = $(event.target); // The clicked button
    
      $(this).closest('.modal').one('hidden.bs.modal', function() {
        // Fire if the button element 
        console.log('The button that closed the modal is: ', $button);
      });
    });
    

    还值得一提的是,.one() method 每次附加时只会触发一次事件(这正是我们想要的)。否则,如果您使用 .on().click() 附加事件,则该事件可能会触发多次,因为每次触发 click 事件侦听器时都会重新附加该事件。


    选项 #2

    根据相关的Bootstrap documentationshow.bs.modal/shown.bs.modal 事件具有附加到事件的relatedTarget 属性。

    如果由单击引起,则单击的元素可用作事件的relatedTarget 属性。

    因此,您可以通过访问模态显示事件侦听器内部的event.relatedTarget 来确定触发模态打开事件的元素:

    Example Here

    $('#delete-file-modal').on('show.bs.modal', function (event) {
        console.log(event.relatedTarget);
    });
    

    请记住,relatedTarget 属性仅与模式显示事件相关联。如果他们有一个与hide.bs.modal/hidden.bs.modal 事件相关联的属性,那就太好了。在撰写本文时,目前没有


    选项#3

    正如 Andrew 在此答案下方指出的 in the comments,您还可以通过访问 document.activeElement 来查看页面上的哪个元素具有焦点。

    在下面的 sn-p 中,事件侦听器附加到模式元素以用于显示和隐藏事件。触发事件时,会检查当前关注的元素是否具有[data-toggle][data-dismiss] 属性(这意味着它确实触发了事件)。

    Example Here

    $('#delete-file-modal').on('hide.bs.modal show.bs.modal', function(event) {
      var $activeElement = $(document.activeElement);
      
      if ($activeElement.is('[data-toggle], [data-dismiss]')) {
        console.log($activeElement);
      }
    });
    

    如果您同时监听显示/隐藏事件(如上例所示),并且想要区分这些事件,您可以查看event.type

    Example Here

    $('#delete-file-modal').on('hide.bs.modal show.bs.modal', function(event) {
      var $activeElement = $(document.activeElement);
      
      if ($activeElement.is('[data-toggle], [data-dismiss]')) {
        if (event.type === 'hide') {
          // Do something with the button that closed the modal
          console.log('The button that closed the modal is: ', $activeElement);
        }
        
        if (event.type === 'show') {
          // Do something with the button that opened the modal
          console.log('The button that opened the modal is: ', $activeElement);
        }
      }
    });
    

    【讨论】:

    • 感谢您提供完美运行的示例。但是我需要检查模态关闭后是否单击了模态内的按钮。有可能吗?
    • 我使用的是 jQuery 3,e.relatedTarget 显示未定义
    • 在 jQuery2.11 中也显示 undefined *** 忽略 *** 专注于模态事件而不是按钮事件...
    • 这也有效: $('#myModal').on('hide.bs.modal', function (e) { var tmpid = $(document.activeElement).attr('id' ); 警报(tmpid); });除非您标识它,否则它不会在模态框上显示“X”....
    • 选项 #3 中的小提琴在 Firefox 57 或 Safari 10.1.2 中不显示警报。这已经过时了吗?不过它可以在 Chrome 中运行。
    【解决方案2】:

    扩展@Jos​​hCrozier 的回答:

    如果他们有一个与 hide.bs.modal/hidden.bs.modal 事件相关联的属性,那就太好了。在撰写本文时,目前还没有


    这将模拟类似的行为,将单击的按钮附加为相关的目标,供以后的听众使用:

    $( '.modal-footer .btn[data-dismiss="modal"]' ).on( 'click', function() {
        var target = this
    
        $( target ).closest( '.modal' )
            .one( 'hide.bs.modal hidden.bs.modal', function( event ) {
                event.relatedTarget = target
            } )
    } )
    

    可以根据模式在项目中的使用方式进一步优化选择器和侦听器。例如:如果你知道你不会使用hide.bs.modal,你可以直接修改hidden.bs.modal的事件。

    【讨论】:

    • 这种方法不考虑用户单击 X 按钮的时间,该按钮位于.modal-header,而不是.modal-footer
    【解决方案3】:

    这也有效:

    $('#myModal').on('hide.bs.modal', function (e) { 
    var tmpid = $(document.activeElement).attr('id'); alert(tmpid); 
    }); 
    

    除非您 id,否则它不会获得模态框上“X”的 id。将返回触发模态关闭的元素的 id....

    【讨论】:

    • 您可能还想对$(document.activeElement).hasClass('btn') 进行检查,以确保它是按钮按下而不是其他任何东西。这就是为什么我必须这样做。我用的是同样的你确定吗?注册和取消提示的对话框。所以,我在显示的按钮上有相同的id。所以,我必须检查按钮的.text() 属性,然后使用.indexOf()。但如果有人点击背景或点击转义,我的 if/then 条件将显示错误的结果。这就是我现在与.hasClass('btn') 联系的原因。
    • 简洁明了。我喜欢它!请注意,这将适用于 hide.bs.modal,但不适用于 hidden.bs.modal。后者将始终将活动元素显示为body,这是有道理的,因为模式已从 DOM 中删除。
    • 这个最好!它不仅会解决我目前遇到的问题,还会定义我未来对引导模式的使用。
    【解决方案4】:

    @JoshCrozier 的答案很好而且很有用,但有时我们需要确定女巫元素触发模式在它关闭后打开/关闭。 @Nomad@JoshCrozier 答案下方的 cmets 中提到了这一点)。

    有时我们还需要确定bodyheader 中的哪个链接或按钮触发了模式关闭(不仅仅是footer 中的按钮)。

    然后我将这个解决方案写到 mix @JoshCrozier @Katia 以我的方式回答并改进最终解决方案

    将此部分添加到页面的脚本中:

    $('body').on('click','.modal .dismiss-modal', function() {
        var closeRelatedTarget = this;
        var $modal = $(closeRelatedTarget).closest('.modal');
        $modal.one('hide.bs.modal hidden.bs.modal', function(event) {
            $modal.data('closeRelatedTarget',closeRelatedTarget);
        });
        $modal.data('closeRelatedTarget','wait');
        $modal.modal('hide');
    });
    $('body').on('show.bs.modal','.modal', function(event){
        $(this).data('closeRelatedTarget','anElement');
        $(this).data('showRelatedTarget',event.relatedTarget);
    });
    

    现在通过简单的事件处理程序轻松使用它或获取目标元素:

    ● 确定女巫元素触发模态以在showshown 显示 (嵌入引导功能):: p>

     $('#MyModal').on('show.bs.modal', function (event) {
         console.log(event.relatedTarget);
     });
    

     $('#MyModal').on('shown.bs.modal', function (event) {
         console.log(event.relatedTarget);
     });
    

    ● 确定女巫元素在hidden

    上触发了关闭模式
     $('#BuyModal').on('hidden.bs.modal', function (event) {
          if($(this).data('closeRelatedTarget')=='wait')
          {return;}
     
          console.log($('#MyModal').data('closeRelatedTarget'));
     });
    

    ● 确定女巫元素触发模态以显示即使在模态关闭后

     console.log($('#MyModal').data('showRelatedTarget'));
    

    ● 确定女巫元素触发模态以关闭即使在模态关闭后

     console.log($('#MyModal').data('closeRelatedTarget'));
    

    注意:而不是data-dismiss="modal" 属性对模型中的每个元素使用我的modal-dismiss 类,您可以关闭模​​型并确定它(不要同时使用modal-dismiss class 和 data-dismiss="modal" 一起)。

    示例: &lt;a href="/more_info.html" class="dismiss-modal"&gt;More info&lt;/a&gt;

    为什么?因为data-dismiss="modal"在我们设置closeRelatedTarget之前关闭了模型并触发了隐藏和隐藏。

    【讨论】:

      【解决方案5】:

      我们想多了。它与标准按钮处理程序一样简单。 data-dismiss="modal" 将使对话框消失,我们仍然会知道我们感兴趣的按钮被点击了。

      $('#delete-file-modal').on('click','#delete-file-modal #confirm-delete-button', function (e) {
        e.preventDefault();
        console.log('confirmed delete');
        return false;
      });
      

      【讨论】:

        【解决方案6】:

        已编辑:我在这里没有看到的与 BOOTSTRAP 4+ 配合良好的解决方案,可以适用于其他版本,包括 v5。如果需要,可能对某人有用。

        <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Annuler</button>
            <button type="button" class="btn btn-primary" data-dismiss="modal">Valider</button>
        </div>
        
        $('#prompt_modal').on('shown.bs.modal', function (event) {
            let buttons = this.querySelectorAll('.btn'); // or others selectors
            buttons.forEach(btn => {
                btn.onclick = () => {
                    console.log(btn);
                    // do something with btn (textCOntent, dataset, classlist, others) 
                    // to detect clicked...
                }
            })
        })
        

        【讨论】:

        • 但这不是纯js方案吗?这是 Jquery。
        • @SiddharthBhansali 这是真的!事实上,“(在引导调用函数中)”的意思是除了引导函数调用本身之外。但我把它拿出来......假设使用 v5,它是可能的......
        猜你喜欢
        • 2023-04-01
        • 1970-01-01
        • 2018-10-06
        • 2021-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-26
        • 1970-01-01
        相关资源
        最近更新 更多