【问题标题】:jQuery UI - Close Dialog When Clicked OutsidejQuery UI - 在外部单击时关闭对话框
【发布时间】:2011-02-03 00:43:01
【问题描述】:

我有一个 jQuery UI 对话框,当单击特定元素时会显示该对话框。如果点击发生在触发元素或对话框本身之外的任何地方,我想关闭对话框。

这是打开对话框的代码:

$(document).ready(function() {
    var $field_hint = $('<div></div>')
        .dialog({
            autoOpen: false,
            minHeight: 50,
            resizable: false,
            width: 375
        });

    $('.hint').click(function() {
        var $hint = $(this);
        $field_hint.html($hint.html());
        $field_hint.dialog('option', 'position', [162, $hint.offset().top + 25]);
        $field_hint.dialog('option', 'title', $hint.siblings('label').html());
        $field_hint.dialog('open');
    });
    /*$(document).click(function() {
        $field_hint.dialog('close');
    });*/
});

如果我取消最后一部分的注释,对话框将永远不会打开。我认为这是因为打开对话框的同一次单击再次将其关闭。


最终工作代码
注意:这是使用 jQuery outside events 插件

$(document).ready(function() {
    // dialog element to .hint
    var $field_hint = $('<div></div>')
            .dialog({
                autoOpen: false,
                minHeight: 0,
                resizable: false,
                width: 376
            })
            .bind('clickoutside', function(e) {
                $target = $(e.target);
                if (!$target.filter('.hint').length
                        && !$target.filter('.hintclickicon').length) {
                    $field_hint.dialog('close');
                }
            });

    // attach dialog element to .hint elements
    $('.hint').click(function() {
        var $hint = $(this);
        $field_hint.html('<div style="max-height: 300px;">' + $hint.html() + '</div>');
        $field_hint.dialog('option', 'position', [$hint.offset().left - 384, $hint.offset().top + 24 - $(document).scrollTop()]);
        $field_hint.dialog('option', 'title', $hint.siblings('label').html());
        $field_hint.dialog('open');
    });

    // trigger .hint dialog with an anchor tag referencing the form element
    $('.hintclickicon').click(function(e) {
        e.preventDefault();
        $($(this).get(0).hash + ' .hint').trigger('click');
    });
});

【问题讨论】:

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


    【解决方案1】:

    抱歉拖了这么久,但我使用了下面的。有什么缺点吗?看open函数...

    $("#popup").dialog(
    {
        height: 670,
        width: 680,
        modal: true,
        autoOpen: false,
        close: function(event, ui) { $('#wrap').show(); },
        open: function(event, ui) 
        { 
            $('.ui-widget-overlay').bind('click', function()
            { 
                $("#popup").dialog('close'); 
            }); 
        }
    });
    

    【讨论】:

    • 实际上,这仅在 UI 窗口为模态时才有效。如果您想关闭模式对话框,非常有用
    • 非常好。我只是把它改成了这个,所以我不必明确设置 ID 引用:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
    • 我喜欢这个。是否存在您不希望它模态但仍希望在外部单击以关闭的情况?对我来说没有意义(我猜使用模态你会失去悬停在外部/下方元素上)。
    • @NickSpacek - 当它不是模态的时,我可以将焦点设置到一个字段,打开一个新对话框等,只需单击一下。对于模态对话框,我必须单击两次:一次关闭它,一次执行下一步操作。
    • 谢谢!您还可以利用 jQuery 实时冒泡。 $('body').on('click', '.ui-widget-overlay', close);
    【解决方案2】:

    忘记使用其他插件:

    这里有 3 种方法可以在点击外部 popin 时关闭 jquery UI 对话框:

    如果对话框是模态的/有背景覆盖:http://jsfiddle.net/jasonday/6FGqN/

    jQuery(document).ready(function() {
        jQuery("#dialog").dialog({
            bgiframe: true,
            autoOpen: false,
            height: 100,
            modal: true,
            open: function(){
                jQuery('.ui-widget-overlay').bind('click',function(){
                    jQuery('#dialog').dialog('close');
                })
            }
        });
    }); 
    

    如果对话框是非模态的方法一:方法一:http://jsfiddle.net/jasonday/xpkFf/

     // Close Pop-in If the user clicks anywhere else on the page
                         jQuery('body')
                          .bind(
                           'click',
                           function(e){
                            if(
                             jQuery('#dialog').dialog('isOpen')
                             && !jQuery(e.target).is('.ui-dialog, a')
                             && !jQuery(e.target).closest('.ui-dialog').length
                            ){
                             jQuery('#dialog').dialog('close');
                            }
                           }
                          );
    

    非模态对话框方法二:http://jsfiddle.net/jasonday/eccKr/

      $(function() {
                $( "#dialog" ).dialog({
                    autoOpen: false, 
                    minHeight: 100,
                    width: 342,
                    draggable: true,
                    resizable: false,
                    modal: false,
                    closeText: 'Close',
                      open: function() {
                          closedialog = 1;
                          $(document).bind('click', overlayclickclose);
                      },
                      focus: function() {
                          closedialog = 0;
                      },
                      close: function() {
                          $(document).unbind('click');
                      }
    
    
    
            });
    
             $('#linkID').click(function() {
                $('#dialog').dialog('open');
                closedialog = 0;
            });
    
             var closedialog;
    
              function overlayclickclose() {
                  if (closedialog) {
                      $('#dialog').dialog('close');
                  }
    
                  //set to one because click on dialog box sets to zero
                  closedialog = 1;
              }
    
    
      });
    

    【讨论】:

    • 太棒了!我稍微更改了模态对话框的打开选项功能,因此无需显式命名元素。 open : function () { $('.ui-widget-overlay').on('click', function () { $(this).parents("body").find(".ui-dialog-content").dialog("close"); }); }
    • 请注意,对于解决方案 #2,.is('.ui-dialog, a') 必须更改为 .is('.ui-dialog, whateverYouClickOnToOpenTheDialog')
    • @Jason 因为逗号,我认为这行实际上是在说“不是 ui-dialog 或页面中的任何链接”。如果我将示例中的“打开对话框”链接更改为 ,则对话框在打开后立即关闭,因为最后触发了窗口事件,这就是为什么我认为您需要排除您单击的项目以打开对话。我不明白您为什么需要在对话框中引用链接?
    • @personne3000 - 实际上你对上下文是正确的,选择器同时选择了两者。我试图记住我为什么添加它,因为我一定有一个我现在不记得的特定原因。
    • @Jason 避免与多个对话框发生冲突,您可以使用命名空间事件click.myNamespace
    【解决方案3】:

    查看jQuery Outside Events plugin

    让你做:

    $field_hint.bind('clickoutside',function(){
        $field_hint.dialog('close');
    });
    

    【讨论】:

    • 我得到了相同的行为,因为单击 $('.hint') 元素时不会显示提示。这些元素在对话框“外部”。
    • 如果对话框打开,你只关心外面的点击。所以打开后才绑定。
    • 我在另一个地方读到了关于基于事件的过滤,这解决了这个问题:groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
    • 对话框在文档中被重复使用了几次,所以我必须有办法在关闭对话框时解除绑定。我认为过滤是一个更简单的解决方案。
    【解决方案4】:

    只需添加这个全局脚本,它会关闭所有模态对话框,只需在外部单击它们即可。

    $(document).ready(function()
    {
        $(document.body).on("click", ".ui-widget-overlay", function()
        {
            $.each($(".ui-dialog"), function()
            {
                var $dialog;
                $dialog = $(this).children(".ui-dialog-content");
                if($dialog.dialog("option", "modal"))
                {
                    $dialog.dialog("close");
                }
            });
        });;
    });
    

    【讨论】:

    • 我没有使用模式对话框。这里投票最多的答案也适用于模态对话框。
    • 当在同一个页面上多次使用同一个对话框时,这是唯一的方法,因为如果你在 open 函数中绑定它,它只会工作一次。感谢这个好主意!
    • 这是我的:$(document).on('click', '.ui-widget-overlay', function() { $('#'+$('.ui-dialog-content')[0].id).dialog('close'); });
    【解决方案5】:
    $(".ui-widget-overlay").click (function () {
        $("#dialog-id").dialog( "close" );
    });
    

    Fiddle 显示了上面的代码。

    【讨论】:

    • 我去看看。谢谢珍!
    • 我使用了这个解决方案。很简单!
    【解决方案6】:

    我必须做两部分。首先是外部点击处理程序:

    $(document).on('click', function(e){
        if ($(".ui-dialog").length) {
            if (!$(e.target).parents().filter('.ui-dialog').length) {
                $('.ui-dialog-content').dialog('close');
            }
        }
    }); 
    

    这会在通用ui-dialog-content 类上调用dialog('close'),因此如果点击不是源自一个对话框,则会关闭所有对话框。它也适用于模态对话框,因为覆盖不是.ui-dialog 框的一部分。

    问题是:

    1. 大多数对话框是由于在对话框外单击而创建的
    2. 此处理程序在这些点击创建一个对话框并冒泡到文档后运行,因此它会立即关闭它们。

    为了解决这个问题,我必须将 stopPropagation 添加到这些点击处理程序中:

    moreLink.on('click', function (e) {
        listBox.dialog();
        e.stopPropagation(); //Don't trigger the outside click handler
    });
    

    【讨论】:

    • 这听起来比我使用的解决方案简单。我得试试看。
    • 这是我自己想到的解决方案,但我的是单行:$('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
    【解决方案7】:

    这个问题有点老了,但如果有人想在用户点击某个地方时关闭一个非模态对话框,你可以使用我从JQuery UI Multiselect plugin 获取的这个问题。主要优点是点击不会“丢失”(如果用户想要点击链接或按钮,则操作完成)。

    $myselector.dialog({
                title: "Dialog that closes when user clicks outside",
                modal:false,
                close: function(){
                            $(document).off('mousedown.mydialog');
                        },
                open: function(event, ui) { 
                        var $dialog = $(this).dialog('widget');
                        $(document).on('mousedown.mydialog', function(e) {
                            // Close when user clicks elsewhere
                            if($dialog.dialog('isOpen') && !$.contains($myselector.dialog('widget')[0], e.target)){
                                $myselector.dialog('close');
                            }            
                        });
                    }                    
                });
    

    【讨论】:

    • 我不得不在点击事件处理程序中移动var $dialog = $(this).dialog('widget');
    • @Melanie,我认为您的解决方案比其他解决方案更适用。一个人根据你的方法为“jqui dialog”创建了插件 - js at github
    【解决方案8】:

    您无需使用任何额外的插件即可做到这一点

    var $dialog= $(document.createElement("div")).appendTo(document.body);
        var dialogOverlay;
    
        $dialog.dialog({
            title: "Your title",
            modal: true,
            resizable: true,
            draggable: false,
            autoOpen: false,
            width: "auto",
            show: "fade",
            hide: "fade",
            open:function(){
                $dialog.dialog('widget').animate({
                    width: "+=300", 
                    left: "-=150"
                });
    
    //get the last overlay in the dom
                $dialogOverlay = $(".ui-widget-overlay").last();
    //remove any event handler bound to it.
                $dialogOverlay.unbind();
                $dialogOverlay.click(function(){
    //close the dialog whenever the overlay is clicked.
                    $dialog.dialog("close");
                });
            }
        });
    

    这里的 $dialog 是对话框。 我们所做的基本上是在打开此对话框时获取最后一个覆盖小部件,并将单击处理程序绑定到该覆盖以关闭 $dialog,就像单击覆盖一样。

    【讨论】:

    • 我认为这类似于模式对话框的其他解决方案。我的问题是关于非模态对话框。
    【解决方案9】:

    不需要外部事件插件...

    只需将事件处理程序添加到 .ui-widget-overlay div:

    jQuery(document).on('click', 'body > .ui-widget-overlay', function(){
         jQuery("#ui-dialog-selector-goes-here").dialog("close");
         return false;
    });
    

    只要确保您用于 jQuery ui 对话框的任何选择器也会被调用以关闭它。即 #ui-dialog-selector-goes-here

    【讨论】:

    • 已经提出了几种关闭模式对话框的解决方案。我的对话框是非模态的,因此没有覆盖。
    • 您只需将点击事件绑定到正文标签或 div 包装器并将其用作您的点击事件触发器,而不是模式。
    • 是的。这基本上就是我的解决方案所做的。它还必须排除对话框中的点击。
    【解决方案10】:

    这不使用 jQuery UI,但确实使用了 jQuery,并且可能对那些出于任何原因不使用 jQuery UI 的人有用。这样做:

    function showDialog(){
      $('#dialog').show();
      $('*').on('click',function(e){
        $('#zoomer').hide();
      });
    }
    
    $(document).ready(function(){
    
      showDialog();    
    
    });
    

    所以,一旦我显示了一个对话框,我就添加了一个点击处理程序,它只查找对任何内容的第一次点击。

    现在,如果我能让它忽略对#dialog 及其内容的任何点击,那就更好了,但是当我尝试将 $('*') 与 $(':not("#dialog,#dialog *")'),它仍然检测到#dialog 点击。

    无论如何,我只是将它用于照片灯箱,所以它可以用于此目的。

    【讨论】:

      【解决方案11】:

      给定的示例使用一个 ID 为“#dialog”的对话框,我需要一个关闭任何对话框的解决方案:

      $.extend($.ui.dialog.prototype.options, {
          modal: true,
          open: function(object) {
              jQuery('.ui-widget-overlay').bind('click', function() {              
                  var id = jQuery(object.target).attr('id');
                  jQuery('#'+id).dialog('close');
              })
          }
      });
      

      感谢我的同事 Youri Arkesteijn 提出使用原型的建议。

      【讨论】:

        【解决方案12】:

        这是对我的非模态对话框有效的唯一方法

        $(document).mousedown(function(e) {
            var clicked = $(e.target); // get the element clicked
            if (clicked.is('#dlg') || clicked.parents().is('#dlg') || clicked.is('.ui-dialog-titlebar')) {
                return; // click happened within the dialog, do nothing here
            } else { // click was outside the dialog, so close it
                $('#dlg').dialog("close");
            }
        });
        

        所有功劳归于 Axle
        Click outside non-modal dialog to close

        【讨论】:

          【解决方案13】:

          对于您感兴趣的人,我创建了一个通用插件,可以在单击对话框外部时关闭对话框,无论是模态对话框还是非模态对话框。它支持同一页面上的一个或多个对话框。

          更多信息在这里:http://www.coheractio.com/blog/closing-jquery-ui-dialog-widget-when-clicking-outside

          劳伦特

          【讨论】:

            【解决方案14】:

            我使用基于此处发布的解决方案:

            var g_divOpenDialog = null;
            function _openDlg(l_d) {
            
              // http://stackoverflow.com/questions/2554779/jquery-ui-close-dialog-when-clicked-outside
              jQuery('body').bind(
               'click',
               function(e){
                if(
                  g_divOpenDialog!=null 
                  && !jQuery(e.target).is('.ui-dialog, a')
                  && !jQuery(e.target).closest('.ui-dialog').length
                ){
                  _closeDlg();
                }
               }
              );
            
              setTimeout(function() {
                g_divOpenDialog = l_d;
                g_divOpenDialog.dialog();
              }, 500);
            }
            function _closeDlg() {
              jQuery('body').unbind('click');
              g_divOpenDialog.dialog('close');
              g_divOpenDialog.dialog('destroy');
              g_divOpenDialog = null;
            }
            

            【讨论】:

              【解决方案15】:

              在一页上制作预览模式时我遇到了同样的问题。经过大量谷歌搜索后,我发现这个非常有用的解决方案。使用事件和目标,它正在检查点击发生的位置,并根据它触发操作或不执行任何操作。

              Code Snippet Library site

              $('#modal-background').mousedown(function(e) {
              var clicked = $(e.target);  
              if (clicked.is('#modal-content') || clicked.parents().is('#modal-content')) 
                  return; 
              } else {  
               $('#modal-background').hide();
              }
              });
              

              【讨论】:

                【解决方案16】:

                其实很简单,你不需要任何插件,只需要 jquery 或者你可以用简单的 javascript 来完成。

                $('#dialog').on('click', function(e){
                  e.stopPropagation();
                });
                $(document.body).on('click', function(e){
                  master.hide();
                });
                

                【讨论】:

                  【解决方案17】:

                  我不认为在整个 DOM 中使用 $('.any-selector') 来查找对话框内容是如此的好。

                  试试

                  $('<div />').dialog({
                      open: function(event, ui){
                          var ins = $(this).dialog('instance');
                          var overlay = ins.overlay;
                          overlay.off('click').on('click', {$dialog: $(this)}, function(event){
                              event.data.$dialog.dialog('close');
                          });
                      }
                  });
                  

                  您实际上是从它所属的对话框实例中获取叠加层,这样永远不会出错。

                  【讨论】:

                  • 这是一个模态对话框?我的 OP 是关于非模态的,所以没有覆盖。
                  【解决方案18】:

                  通过以下代码,您可以模拟单击对话框的“关闭”按钮(将字符串“MY_DIALOG”更改为您自己的对话框名称)

                  $("div[aria-labelledby='ui-dialog-title-MY_DIALOG'] div.ui-helper-clearfix a.ui-dialog-titlebar-close")[0].click();
                  

                  【讨论】:

                    【解决方案19】:

                    智能代码: 我正在使用以下代码,以便每件事都保持清晰易读。 out side body 将关闭对话框。

                    $(document).ready(function () {
                       $('body').on('click', '.ui-widget-overlay', closeDialogBox);
                    });
                    
                    function closeDialogBox() {
                        $('#dialog-message').dialog('close');
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      我最终使用了这段代码,它应该适用于页面上任何打开的对话框,忽略工具提示上的点击,并清理正在关闭的对话框的资源。

                      
                              $(document).mousedown(function(e) {
                                  var clicked = $(e.target); // get the element clicked
                                  if (clicked.is('.ui-dialog-content, .ui-dialog-titlebar, .ui-tooltip') || clicked.parents().is('.ui-dialog-content, .ui-dialog-titlebar, .ui-tooltip')) {
                                      return; // click happened within the dialog, do nothing here
                                  } else { // click was outside the dialog, so close it
                                      $('.ui-dialog-content').dialog("close");
                                      $('.ui-dialog-content').dialog("destroy");
                                      $('.ui-dialog-content').detach();
                      
                                  }
                              });
                      

                      【讨论】:

                        【解决方案21】:

                        我刚刚遇到需要通过单击元素外来关闭 .dialog(s)。我有一个包含很多信息对话框的页面,所以我需要一些东西来处理它们。我是这样处理的:

                        $(document).ready(function () {    
                            $(window).click(function (e) {
                                $(".dialogGroup").each(function () {
                                    $(this).dialog('close');
                                })
                            });
                            $("#lostEffClick").click(function () {
                                event.stopPropagation();
                                $("#lostEffDialog").dialog("open");
                            };
                        });
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2012-01-08
                          • 1970-01-01
                          • 1970-01-01
                          • 2016-01-20
                          • 1970-01-01
                          • 1970-01-01
                          • 2016-07-16
                          相关资源
                          最近更新 更多