jQuery UI - Dışarıda Tıklandığında İletişim Kutusunu Kapat


113

Belirli öğeler tıklandığında görüntülenen bir jQuery UI İletişim Kutum var. Bu tetikleyici öğeler veya iletişim kutusunun kendisi dışında herhangi bir yerde bir tıklama olursa, iletişim kutusunu kapatmak istiyorum.

İletişim kutusunu açma kodu:

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

Son bölümü geri alırsam, iletişim kutusu asla açılmıyor. Sanırım diyaloğu açan aynı tıklamanın onu tekrar kapatmasından kaynaklanıyor.


Son Çalışma Kodu
Not: Bu, jQuery dışındaki olaylar eklentisini kullanıyor

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

Yanıtlar:


31

JQuery Outside Events eklentisine göz atın

Yapmanıza izin verir:

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

Aynı davranışı görüyorum, çünkü ipucu $ ('. İpucu') öğeleri tıklandığında görüntülenmiyor. Bu öğeler iletişim kutusunun 'dışındadır'.
Sonny

Yalnızca iletişim kutusu açıksa dışarıdaki tıklamayı önemsersiniz. Bu yüzden sadece açtıktan sonra bağlayın.
PetersenDidIt

3
Etkinliğe dayalı filtreleme hakkında başka bir yerde okudum ve bu sorunu çözdü: groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
Sonny

İletişim kutusu belgede birkaç kez yeniden kullanıldığından, iletişim kutusunu kapatırken bağlantıyı çözmenin bir yolunu bulmalıyım. Filtrelemenin daha basit bir çözüm olduğunu düşünüyorum.
Sonny

159

Bu kadar uzun süre sonra bunu sürüklediğim için üzgünüm ama aşağıdakileri kullandım. Herhangi bir dezavantaj var mı? Açık işleve bakın ...

$("#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
Aslında bu, yalnızca UI penceresi kalıcı ise işe yarar. Kalıcı bir iletişim kutusunu kapatmak istiyorsanız çok kullanışlıdır
stumac85

37
Çok hoş. Bunu yeni değiştirdim, böylece kimlik referansını açıkça belirtmek zorunda kalmadım:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
James McCormack

1
Bunu beğendim. Modal istemediğiniz ancak yine de kapatmak için dışarıda tıklamayı istediğiniz bir durum var mı? Bana mantıklı gelmiyor (sanırım modal ile öğelerin dışında / altında gezinmeyi kaybedersiniz).
Nick Spacek

3
@NickSpacek - Modal olmadığında, odağı bir alana ayarlayabilir, yeni bir iletişim kutusu açabilir, vb. Tek bir tıklama ile. Kalıcı bir iletişim kutusu ile iki tıklama kullanmam gerekir: biri kapatmak için ve diğeri sonraki eylemi yapmak.
Sonny

1
Teşekkürler! Ayrıca jQuery canlı köpürmeden de yararlanabilirsiniz. $ ['gövde']. on ('tıklayın', '.ui-widget-overlay', kapat);
Quang Van

78

Başka bir eklenti kullanmayı unutun:

Dışarıda açılır pencereye tıklandığında bir jquery UI iletişim kutusunu kapatmak için 3 yöntem şunlardır:

İletişim kutusu kalıcıysa / arka plan kaplaması varsa: 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');
            })
        }
    });
}); 

İletişim kutusu kalıcı değilse Yöntem 1: yöntem 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');
                        }
                       }
                      );

Kalıcı Olmayan iletişim kutusu Yöntem 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
Harika! Kalıcı iletişim kutusu için açık seçenek işlevini biraz değiştirdim, bu nedenle öğeyi açıkça adlandırmaya gerek yok. open : function () { $('.ui-widget-overlay').on('click', function () { $(this).parents("body").find(".ui-dialog-content").dialog("close"); }); }
meridius

2. çözüm için .is ('. Ui-dialog, a') 'nin .is ('. Ui-dialog, ne olursa olsunYouClickOnToOpenTheDialog ') olarak değiştirilmesi gerektiğine dikkat edin
personne3000

@ Jason, virgülden dolayı, sanırım bu satır "ui-dialog veya sayfadaki herhangi bir bağlantı değil" diyor. Örneğinizdeki "Aç iletişim kutusu" bağlantısını bir <span> olarak değiştirirsem, pencere olayı en son tetiklendiğinden, iletişim kutusu açıldıktan hemen sonra kapatılır, bu nedenle, iletişim. Neden iletişim kutusundaki bağlantılara başvurmanız gerektiğini anlamıyorum?
personne3000

@ personne3000 - aslında bağlam konusunda haklısınız, seçici ikisini de seçiyor. Bunu neden eklediğimi hatırlamaya çalışıyorum, çünkü şu anda hatırlamadığım belirli bir nedene sahip olmalıyım.
Jason

@Jason, birden fazla diyalogla çakışmaları önlemek için isim alanlı olayları kullanabilirsinizclick.myNamespace
Christophe Roussy

17

Sadece bu genel betiği ekleyin, böylece tüm kalıcı diyalogları yalnızca site dışına tıklarsanız kapatır.

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

Kalıcı bir iletişim kutusu kullanmıyorum. Buradaki en fazla oylama ile cevap, modal diyaloglar için de geçerlidir.
Sonny

Aynı iletişim kutusunu aynı sayfada birden fazla kullandığınızda, bunu açmanın tek yolu budur çünkü onu açık işlevde bağlarsanız yalnızca bir kez çalışır. Bu harika fikir için teşekkürler!
MaDaHoPe

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

Yukarıdaki kodu çalışırken gösteren keman .


Bir bakacağım. Teşekkürler Jen!
Sonny

8

İki bölüm yapmam gerekiyordu. Önce dış tıklama işleyici:

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

Bu dialog('close'), jenerik ui-dialog-contentsınıfı çağırır ve bu nedenle, eğer tıklama bir taneden kaynaklanmadıysa tüm diyalogları kapatır. Yer paylaşımı .ui-dialogkutunun bir parçası olmadığı için kalıcı iletişim kutuları ile de çalışacaktır .

Problem şu:

  1. Çoğu iletişim kutusu, bir iletişim kutusunun dışındaki tıklamalar nedeniyle oluşturulur
  2. Bu işleyici, bu tıklamalar bir iletişim kutusu oluşturduktan ve belgeye köpürdükten sonra çalışır, böylece onları hemen kapatır.

Bunu düzeltmek için, bu tıklama işleyicilerine stopPropagation eklemem gerekiyordu:

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

Bu, kullandığım çözümden daha basit geliyor. Bunu denemek zorunda kalacağım.
Sonny

$('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
Kendi

5

Bu soru biraz eski, ancak birisi bir yere tıkladığında kalıcı OLMAYAN bir iletişim kutusunu kapatmak isterse, bunu JQuery UI Multiselect eklentisinden aldığım kullanabilirsiniz . Ana avantaj, tıklamanın "kaybolmaması" (kullanıcı bir bağlantıya veya düğmeyi tıklamak isterse, işlem yapılır).

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

Harekete geçmek zorundaydım var $dialog = $(this).dialog('widget');üzerinde tıklama olay işleyicisi içinde
Stefan Haberl

1
@Melanie, bence çözümün diğerlerinden daha uygulanabilir. Bir adam yaklaşımınıza göre 'jqui diyalog' için eklenti oluşturdu - js at github
resnyanskiy

5

Bunu herhangi bir ek eklenti kullanmadan yapabilirsiniz

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

Burada $ dialog diyalogdur. Temelde yaptığımız şey, bu iletişim kutusu her açıldığında son yer paylaşımı widget'ını almak ve bu kaplamaya bir tıklama işleyicisini, kaplama tıklandığında $ dialog'u kapatmak için bağlamaktır.


Bunun modsal bir diyalog için diğer çözümlere benzediğini düşünüyorum. Benim sorum mod olmayan diyaloglar içindi.
Sonny

5

dış etkinlikler eklentisine gerek yok ...

sadece .ui-widget-overlay div öğesine bir olay işleyicisi ekleyin:

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

jQuery kullanıcı arabirimi diyaloğu için kullandığınız seçicinin aynı zamanda onu kapatmak için çağrıldığından emin olun .. yani # ui-dialog-selector-goes-here


Modsal diyalogların kapatılması için çeşitli çözümler halihazırda önerilmiştir. Diyaloğum kipli değil ve bu nedenle kaplamasız.
Sonny

Daha sonra, tıklama etkinliğini gövde etiketine veya div sarmalayıcısına bağlamanız ve bunu modal yerine tıklama etkinliği tetikleyiciniz olarak kullanmanız yeterlidir.
Jonathan Marzullo

Evet. Benim çözümümün yaptığı şey bu. Ayrıca, iletişim kutusundaki tıklamaları da dışlaması gerekir.
Sonny

3

Bu, jQuery UI kullanmaz, ancak jQuery kullanır ve herhangi bir nedenle jQuery UI kullanmayanlar için yararlı olabilir. Böyle yapın:

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

$(document).ready(function(){

  showDialog();    

});

Bu yüzden, bir iletişim kutusu gösterdikten sonra, herhangi bir şeye yalnızca ilk tıklamayı arayan bir tıklama işleyici ekliyorum.

Şimdi, #dialog ve içeriğindeki herhangi bir şeydeki tıklamaları göz ardı etmesini sağlayabilirsem, ancak $ ('*') 'ı $ (': not ("# dialog, # dialog *") ile değiştirmeyi denediğimde daha iyi olurdu. '), yine de #dialog tıklamaları tespit etti.

Her neyse, bunu sadece bir fotoğraf ışık kutusu için kullanıyordum, bu yüzden bu amaç için iyi çalıştı.


2

Verilen örnekler '#dialog' kimliğine sahip bir iletişim kutusu kullanıyor, herhangi bir iletişim kutusunu kapatan bir çözüme ihtiyacım vardı:

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

Prototip kullanma önerisi için meslektaşım Youri Arkesteijn'e teşekkürler.


2

MODAL OLMAYAN iletişim kutusu için benim için çalışan tek yöntem budur

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

Tüm kredi Axle'a gider
Kapatmak için modal olmayan iletişim kutusunun dışındaki tıklayın



1

Bu çözümü burada yayınlanan birine dayanarak kullanıyorum:

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

Tek sayfada önizleme modeli yaparken aynı sorunu yaşadım. Bir sürü googling yaptıktan sonra bu çok kullanışlı çözümü buldum. Olay ve hedef ile, tıklamanın nerede olduğunu kontrol eder ve buna bağlı olarak eylemi tetikler veya hiçbir şey yapmaz.

Code Snippet Kitaplığı sitesi

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

Aslında basit, aslında herhangi bir eklentiye ihtiyacınız yok, sadece jquery veya basit bir javascript ile yapabilirsiniz.

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

0

Tüm DOM'dan $ ('. Any-selector') kullanarak iletişim kutusu bulmanın o kadar parlak olduğunu sanmıyorum.

Deneyin

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

Bindirmeyi gerçekten ait olduğu diyalog örneğinden alıyorsunuz, işler asla bu şekilde ters gitmeyecek.


Bu kalıcı bir iletişim kutusu için mi? Benim OP'm kipsizdir, bu yüzden kaplama yoktur.
Sonny

0

Aşağıdaki kodla, iletişim kutusunun 'kapat' düğmesine bir tıklamayı simüle edebilirsiniz (kendi iletişim pencerenizin adı için 'MY_DIALOG' dizesini değiştirin)

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

0

Akıllı Kod: Her şeyin net ve okunaklı kalması için aşağıdaki kodu kullanıyorum. dış gövde iletişim kutusunu kapatır.

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

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

0

Sayfadaki açık iletişim kutularında çalışması gereken, araç ipuçlarındaki tıklamaları yok sayan ve kapatılan iletişim kutusunun kaynaklarını da temizleyen bu kodu kullandım.


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

            }
        });
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.