jQuery UI - закрывать диалог при нажатии снаружи

103

У меня есть диалоговое окно 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');
    });
});
Теги:
jquery-ui-dialog

18 ответов

28
Лучший ответ

Откроется плагин jQuery Outside Events

Позволяет выполнить следующие действия:

$field_hint.bind('clickoutside',function(){
    $field_hint.dialog('close');
});
  • 0
    Я получаю то же поведение, в том, что подсказка не будет отображаться при нажатии элементов $ ('. Hint'). Эти элементы находятся «вне» диалога.
  • 0
    Вы только заботитесь о щелчке снаружи, если диалог открыт. Так что связывай его только после того, как откроешь.
Показать ещё 2 комментария
154

Извините, что перетащил его так долго, но я использовал ниже. Любые недостатки? См. Открытую функцию...

$("#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
    На самом деле это будет работать только в том случае, если окно пользовательского интерфейса является модальным. Хорошо полезно, если вы хотите закрыть модальный диалог
  • 35
    Очень хорошо. Я просто изменил его на это, поэтому мне не нужно было явно $('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); }); ссылку на идентификатор: $('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
Показать ещё 7 комментариев
76

Забудьте использовать другой плагин:

Ниже приведены 3 метода закрытия диалогового окна пользовательского интерфейса jquery при нажатии за пределами popin:

Если диалог является модальным/имеет фоновое наложение: 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;
          }


  });
  • 1
    Мне нравится твой стиль.
  • 7
    +1 за работу без плагинов и использование оверлея
Показать ещё 9 комментариев
14

Просто добавьте этот глобальный script, который закрывает все модальные диалоги, просто нажимая на них.

$(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");
            }
        });
    });;
});
  • 0
    Я не использую модальный диалог. Ответ здесь с наибольшим количеством голосов также для модальных диалогов.
  • 0
    При использовании одного и того же диалога более одного раза на одной странице, это единственный путь, так как он будет работать только один раз, если вы связываете его в функции открытия. Спасибо за эту прекрасную идею!
Показать ещё 1 комментарий
10
$(".ui-widget-overlay").click (function () {
    $("#dialog-id").dialog( "close" );
});

Fiddle, показывая приведенный выше код в действии.

  • 0
    Я посмотрю на это. Спасибо Джен!
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, и поэтому закроет диалоговые окна all, если щелчок не возник из одного. Он также будет работать с модальными диалогами, поскольку наложение не является частью поля .ui-dialog.

Проблема заключается в следующем:

  • Большинство диалогов создаются из-за кликов вне диалогового окна
  • Этот обработчик запускается после того, как эти клики создали диалоговое окно и пузырились до документа, поэтому он немедленно закрывает их.

Чтобы исправить это, мне пришлось добавить stopPropagation для этих обработчиков кликов:

moreLink.on('click', function (e) {
    listBox.dialog();
    e.stopPropagation(); //Don't trigger the outside click handler
});
  • 0
    Это звучит проще, чем решение, которое я использую. Я должен буду попробовать это.
  • 0
    Это решение, которое я подумал о себе, но мое решение состоит из одной строки: $('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
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 - диалог. В основном мы делаем, чтобы получить последний оверлейный виджет при открытии этого диалога и привязать обработчик кликов к этому наложению, чтобы закрыть диалоговое окно $, как и при нажатии на оверлей.

  • 0
    Я думаю, что это похоже на другие решения для модального диалога. Мой вопрос был о немодальных диалогах.
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');
                        }            
                    });
                }                    
            });
  • 0
    Мне пришлось переместить var $dialog = $(this).dialog('widget'); внутри обработчика события по нажатию
  • 1
    @ Мелани, я думаю, что ваше решение более применимо, чем другие. Один парень создал плагин для 'jqui dialog' на основе вашего подхода - js на github
4

нет необходимости в плагине внешних событий...

просто добавьте обработчик событий в .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-go-here

  • 0
    Несколько решений для закрытия модальных диалогов уже были предложены. Мой диалог не модальный, и поэтому не имеет оверлея.
  • 0
    Чем просто связать событие click с тегом body или div-оберткой и использовать его в качестве триггера события click вместо модального.
Показать ещё 2 комментария
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');
        })
    }
});

Спасибо моему коллеге вашему Arkesteijn за предложение использовать прототип.

1

Это единственный метод, который работал у меня для моего диалогового окна NON-MODAL

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

У меня была такая же проблема, пока вы просматривали модальный текст на одной странице. После многих поисковых запросов я нашел это очень полезное решение. С событием и целью он проверяет, где произошло щелчок, и в зависимости от него срабатывает действие или ничего не делает.

Сайт библиотеки фрагментов кода

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

Для тех, кого вас интересует, я создал общий плагин, который позволяет закрыть диалог при нажатии вне его, будь то модальный или немодальный диалог. Он поддерживает один или несколько диалогов на одной странице.

Дополнительная информация здесь: http://www.coheractio.com/blog/closing-jquery-ui-dialog-widget-when-clicking-outside

Лоран

0

С помощью следующего кода вы можете имитировать щелчок по кнопке "закрыть" в диалоговом окне (измените строку "MY_DIALOG" для имени вашего собственного диалога)

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

Я не думаю, что поиск диалога с использованием $('. any-selector') из всего DOM настолько яркий.

Try

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

Вы действительно получаете оверлей из экземпляра диалогового окна, к которому он принадлежит, поэтому все будет не так.

  • 0
    Это для модального диалога? Мой ОП о немодальном, так что нет наложения.
0

Это просто на самом деле вам не нужны никакие плагины, просто jquery или вы можете сделать это с помощью простого javascript.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню