Користувальницький інтерфейс 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.