Користувальницький інтерфейс jQuery - закрити діалогове вікно при натисканні назовні


113

У мене є діалогове вікно інтерфейсу jQuery, яке відображається при натисканні конкретних елементів. Я б хотів закрити діалогове вікно, якщо клацання відбувається де-небудь, крім тих, що викликають елементи або самого діалогу.

Ось код для відкриття діалогового вікна:

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

Відповіді:


31

Перевірте плагін jQuery Outside Events

Дозволяє робити:

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

Я маю таку ж поведінку, що підказка не відображатиметься при натисканні елементів $ ('. Hint'). Ці елементи знаходяться "поза" діалогового вікна.
— Сонні

Вас цікавить лише клацання зовні, якщо діалогове вікно відкрите. Тож зв’яжіть його лише після того, як ви відкриєте його.
— PetersenDidIt

3
Я читав в іншому місці про фільтрування на основі події, і це вирішило проблему: groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
— Сонні,

Діалогове вікно повторно використовується в документі кілька разів, тому я мав би мати спосіб скасувати зв'язок при закритті діалогового вікна. Я думаю, що фільтрація - це більш просте рішення.
— Сонні

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
Насправді це буде працювати лише в тому випадку, якщо вікно інтерфейсу користувача модальне. Добре корисно, якщо ви хочете закрити модальний діалог
— stumac85

37
Дуже хороша. Я просто змінив це на це, тому мені не довелося чітко встановлювати посилання на ідентифікатор:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
— Джеймс Маккормак

1
Мені це подобається. Чи є випадок, коли ви не хочете, щоб він був модальним, але все ж хочете натиснути зовні, щоб закрити? Для мене це не має сенсу (я думаю, що з модальним способом ви втрачаєте ширяння на зовнішніх і під елементами).
— Нік Спейпк

3
@NickSpacek - коли це не модально, я можу встановити фокус на поле, відкрити нове діалогове вікно тощо лише одним клацанням миші. За допомогою модального діалогового вікна мені доведеться скористатися двома клацаннями: одним, щоб закрити його, і одним, щоб зробити наступну дію.
— Сонні

1
Дякую! Ви також можете скористатись живими дзвінками jQuery. $ ('body'). on ('click', '.ui-widget-overlay', close);
— Куанг Ван

78

Забудьте про використання іншого плагіна:

Ось 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;
          }


  });

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-діалог, що б ви не булиClickOnToOpenTheDialog')
— personne3000

@Jason через коми, я думаю, що цей рядок насправді говорить "не інтерфейс діалогового вікна або будь-яке посилання на сторінці". Якщо я поміняю посилання "Відкрити діалогове вікно" у вашому прикладі на <span>, діалогове вікно закриється відразу після відкриття, коли подія вікна запускається останньою, тому я думаю, що вам потрібно виключити елемент, на який ви натискаєте, щоб відкрити вікно діалог. Я не розумію, чому вам потрібно посилатися на посилання в діалоговому вікні?
— personne3000

@ personne3000 - насправді ти маєш рацію щодо контексту, що селектор вибирає обидва. Я намагаюся згадати, чому я додав це, оскільки, мабуть, у мене була конкретна причина, про яку я зараз не пам’ятаю.
— Джейсон

@Jason, щоб уникнути конфліктів у кількох діалогах, ви можете використовувати події в просторі іменclick.myNamespace
— Крістоф Руссі,

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

Я не використовую модальний діалог. Відповідь тут з найбільшою кількістю голосів - також для модальних діалогів.
— Сонні

При використанні одного і того ж діалогового вікна більше разів на одній і тій же сторінці це єдиний шлях, оскільки він буде працювати лише один раз, якщо ви прив’яжете його до відкритої функції. Дякую за цю чудову ідею!
— MaDaHoPe

ось моя:$(document).on('click', '.ui-widget-overlay', function() { $('#'+$('.ui-dialog-content')[0].id).dialog('close'); });
— mr5

10
$(".ui-widget-overlay").click (function () {
    $("#dialog-id").dialog( "close" );
});

Fiddle, що показує вищевказаний код у дії.


Я погляну на це. Дякую Джен!
— Сонні

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');всередину обробника подій, що працює при натисканні
— Стефан Хаберл

1
@Melanie, я думаю, що ваше рішення є більш застосовним, ніж інші. Один хлопець створив плагін для 'jqui dialog' на основі вашого підходу - js at github
— resnyanskiy

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 - це діалог. Що в основному ми робимо, це отримати останній віджет накладання кожного разу, коли це діалогове вікно відкриється, і прив’язує обробник кліків до цього накладання, щоб закрити діалогове вікно $, коли будь-коли натискається на нього.


Я думаю, це подібне до інших рішень для модального діалогу. Моє запитання стосувалось немодальних діалогів.
— Сонні

5

немає потреби у плагіні зовнішніх подій ...

просто додайте обробник подій у розділ .ui-widget-overlay:

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

просто переконайтеся, що будь-який селектор, який ви використовували для діалогового вікна jQuery, також викликається, щоб закрити його. тобто # ui-dialog-selector-тут


Вже запропоновано кілька рішень для закриття модальних діалогів. Мій діалог немодальний, тому не має накладених.
— Сонні

Тоді ви просто прив’язуєте подію клацання до тегу body або обгортки div та використовуєте це як тригер події клацання, а не модальний.
— Джонатан Марзулло,

Так. Це по суті те, що робить моє рішення. Він також повинен виключати кліки в діалоговому вікні.
— Сонні

3

Це не використовує інтерфейс jQuery, але використовує jQuery, і може бути корисним для тих, хто не використовує інтерфейс jQuery з будь-якої причини. Зробіть так:

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

$(document).ready(function(){

  showDialog();    

});

Отже, як тільки я показав діалогове вікно, я додаю обробник кліків, який шукає лише перший клік на що-небудь.

Тепер було б приємніше, якби я міг змусити її ігнорувати кліки на будь-що на #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');
        })
    }
});

Дякую моєму колезі Юрі Аркештейну за пропозицію використовувати прототип.


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
Click поза немодальним діалоговим діалоговим вікном, щоб закрити


1

Для тих, хто вас цікавить, я створив загальний плагін, який дозволяє закрити діалогове вікно, клацнувши поза ним, будь то модальний чи немодальний діалог. Він підтримує один або кілька діалогів на одній сторінці.

Більше інформації тут: http://www.coheractio.com/blog/closing-jquery-ui-dialog-widget-when-clicking-outside

Лоран


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

Я не думаю, що пошук речей із діалогу за допомогою $ ('. Any-selector') у цілому DOM не є таким яскравим.

Спробуйте

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

За допомогою наступного коду ви можете імітувати клацання кнопки "закрити" діалогового вікна (змінити рядок "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();

            }
        });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.