jQuery UI-在外部单击时关闭对话框


113

我有一个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外部事件插件

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

Answers:


31

查看jQuery Outside Events插件

让您做:

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

我正在得到相同的行为,因为单击$('。hint')元素时不会显示提示。这些元素在对话框“外部”。
桑尼2010年

如果对话框打开,则只关心单击外部。因此,仅在打开后绑定它。
PetersenDidIt,2010年

3
我在另一处阅读了有关基于事件的过滤的信息,该文件解决了问题:groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
桑尼

该对话框在文档中多次重用,因此关闭对话框时,我必须有一种解除绑定的方法。我认为过滤是一个更简单的解决方案。
桑尼2010年

159

很抱歉,拖了很久以后,但我使用了以下内容。有什么缺点吗?查看打开功能...

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

18
实际上,这仅在UI窗口是模式窗口时才有效。如果要关闭模式对话框非常有用
stumac85 2010年

37
非常好。我只是将其更改为此,因此不必显式设置ID引用:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
James McCormack

1
我喜欢这一个。是否存在您不希望它出现模式但仍希望单击外部以关闭它的情况?对我来说没有意义(我想使用模式,您会失去在外部/下方元素上的悬停)。
Nick Spacek 2012年

3
@NickSpacek-当它不是模态时,我可以一键设置焦点,打开一个新对话框等。使用模式对话框时,我必须单击两次:一次将其关闭,然后单击进行下一个操作。
桑尼2012年

1
谢谢!您还可以利用jQuery实时冒泡。$('body')。on('click','.ui-widget-overlay',close);
Quang Van

78

忘记使用其他插件:

单击外部弹出窗口时,以下三种方法可关闭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');
            })
        }
    });
}); 

如果对话框是非模式对话框方法1:方法1: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');
                        }
                       }
                      );

非模式对话框方法2: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;
          }


  });

2
大!我稍微更改了模式对话框的打开选项功能,因此无需显式命名元素。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,everyYouClickOnToOpenTheDialog')
personne3000

@Jason由于逗号,我认为这一行实际上是在说“不是ui对话框或页面中的任何链接”。如果我将示例中的“打开对话框”链接更改为<span>,则对话框在打开后立即关闭,因为最后触发了窗口事件,这就是为什么我认为您需要排除单击以打开窗口项的原因对话。我不明白为什么您需要在对话框中引用链接?
personne3000

@ personne3000-实际上您对上下文是正确的,选择器同时选择了两者。我试图记住我为什么要添加它,因为我肯定有一个我目前不记得的特定原因。
杰森

@Jason为避免与多个对话框发生冲突,可以使用命名空间事件click.myNamespace
Christophe Roussy 2014年

17

只需添加此全局脚本,该脚本将关闭所有模式对话框,只需单击它们的外部即可。

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

我没有使用模式对话框。投票最多的答案也是模式对话框。
桑尼2012年

当在同一页面上多次使用同一对话框时,这是唯一的方法,因为如果在open函数中将其绑定,它将只能使用一次。感谢这个好主意!
MaDaHoPe'8

这是我的:$(document).on('click', '.ui-widget-overlay', function() { $('#'+$('.ui-dialog-content')[0].id).dialog('close'); });
mr5


8

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

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

这将调用dialog('close')通用ui-dialog-content类,因此如果单击不是一次单击就关闭所有对话框。它也可以与模式对话框一起使用,因为覆盖图不是.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'); });
单线的

5

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

$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');点击事件处理程序内
Stefan Haberl 2014年

1
@Melanie,我认为您的解决方案比其他解决方案更适用。一个人根据您的方法为“ jqui对话框”创建了插件-github上的js
resnyanskiy 2015年

5

您可以执行此操作,而无需使用任何其他插件

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。


我认为这类似于模式对话框的其他解决方案。我的问题是非模式对话框。
桑尼

5

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

只需在.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


已经提出了几种用于关闭模式对话框的解决方案。我的对话框是非模式对话框,因此没有覆盖。
桑尼

比起您,您只需将click事件绑定到body标签或div包装器,然后将其用作您的click事件触发器,而不是模式触发器。
Jonathan Marzullo 2014年

是。这基本上就是我的解决方案。它还必须排除对话框中的单击。
桑尼2014年

3

这不使用jQuery UI,但是使用jQuery,对于出于某种原因不使用jQuery UI的用户可能很有用。这样做:

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

$(document).ready(function(){

  showDialog();    

});

因此,一旦显示了一个对话框,便添加一个单击处理程序,该处理程序仅查找对任何内容的首次单击。

现在,如果我能够忽略对#dialog及其内容的单击会更好,但是当我尝试使用$(':not(“#dialog,#dialog *”)切换$('*')时'),它仍然检测到#dialog点击。

无论如何,我纯粹是将它用于照片灯箱,因此可以正常使用。


2

给定的示例使用一个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对使用原型的建议。


2

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

$(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,
在外部非模态对话框中单击以关闭



1

我使用此解决方案的基础是这里发布的一个:

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

1

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

代码段库网站

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

0

这很简单,实际上您不需要任何插件,只需jquery即可,也可以使用简单的javascript做到。

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

0

我不认为从整个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是关于非模式的,因此没有覆盖。
桑尼2015年

0

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

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

0

智能代码:我正在使用以下代码,以便使所有内容保持清晰可读。外侧主体将关闭对话框。

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

function closeDialogBox() {
    $('#dialog-message').dialog('close');
}

0

我最终使用了此代码,该代码应可在页面上的所有打开的对话框中使用,忽略对工具提示的单击,并清除也将关闭的对话框的资源。


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

            }
        });
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.