jQuery UI - Tutup Dialog Saat Diklik Di Luar

113

Saya memiliki Dialog UI jQuery yang ditampilkan ketika elemen tertentu diklik. Saya ingin menutup dialog jika klik terjadi di mana saja selain di elemen pemicu tersebut atau dialog itu sendiri.

Berikut kode untuk membuka dialog:

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

Jika saya menghapus komentar di bagian terakhir, dialog tidak akan pernah terbuka. Saya berasumsi itu karena klik yang sama yang membuka dialog itu menutupnya lagi.


Kode Kerja Akhir
Catatan: Ini menggunakan plugin jQuery outside events

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

Jawaban:

31

Lihat plugin jQuery Outside Events

Memungkinkan Anda melakukannya:

$field_hint.bind('clickoutside',function(){
    $field_hint.dialog('close');
});
PetersenDidIt
sumber
Saya mendapatkan perilaku yang sama, bahwa petunjuk tidak akan ditampilkan ketika elemen $ ('. Hint') diklik. Elemen-elemen tersebut berada 'di luar' dialog.
Sonny
Anda hanya peduli dengan klik di luar jika dialog terbuka. Jadi hanya mengikatnya setelah Anda membukanya.
PetersenDidIt
3
Saya membaca di tempat lain tentang pemfilteran berdasarkan acara tersebut, dan itu memecahkan masalah: groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
Sonny
Dialog tersebut digunakan kembali beberapa kali dalam dokumen, jadi saya harus memiliki cara untuk melepaskan ikatan saat menutup dialog. Saya pikir penyaringan adalah solusi yang lebih sederhana.
Sonny
159

Maaf menyeret ini setelah sekian lama tetapi saya menggunakan yang di bawah ini. Ada kerugian? Lihat fungsi terbuka ...

$("#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'); 
        }); 
    }
});
stumac85
sumber
18
Sebenarnya ini hanya akan berfungsi jika jendela UI adalah modal. Berguna jika Anda ingin menutup dialog modal
stumac85
37
Sangat bagus. Saya baru saja mengubahnya menjadi ini jadi saya tidak perlu menetapkan referensi ID secara eksplisit:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
James McCormack
1
Saya suka yang ini. Apakah ada kasus di mana Anda tidak menginginkannya modal tetapi tetap ingin mengklik di luar untuk menutup? Tidak masuk akal bagi saya (saya kira dengan modal Anda kehilangan hovering di luar / di bawah elemen).
Nick Spacek
3
@NickSpacek - Jika bukan modal, saya dapat mengatur fokus ke bidang, membuka dialog baru, dll. Dengan hanya satu klik. Dengan dialog modal saya harus menggunakan dua klik: satu untuk menutupnya, dan satu lagi untuk melakukan tindakan berikutnya.
Sonny
1
Terima kasih! Anda juga dapat memanfaatkan jQuery live menggelegak. $ ('body'). on ('click', '.ui-widget-overlay', close);
Quang Van
78

Lupakan menggunakan plugin lain:

Berikut adalah 3 metode untuk menutup dialog UI jquery saat mengklik di luar popin:

Jika dialognya modal / memiliki hamparan latar belakang: 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');
            })
        }
    });
}); 

Jika dialog non-modal Metode 1: metode 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');
                        }
                       }
                      );

Metode Dialog Non-Modal 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;
          }


  });
Jason
sumber
2
Bagus! Saya sedikit mengubah fungsi opsi terbuka untuk dialog modal, jadi tidak perlu memberi nama elemen secara eksplisit. open : function () { $('.ui-widget-overlay').on('click', function () { $(this).parents("body").find(".ui-dialog-content").dialog("close"); }); }
meridius
Perhatikan bahwa untuk solusi # 2, .is ('. Ui-dialog, a') harus diubah menjadi .is ('. Ui-dialog, everythingYouClickOnToOpenTheDialog')
personne3000
@Jason karena koma, menurut saya baris ini sebenarnya mengatakan "bukan ui-dialog, atau link apa pun di halaman". Jika saya mengubah tautan "Buka dialog" dalam contoh Anda menjadi <span>, dialog ditutup segera setelah dibuka karena peristiwa jendela dipicu terakhir, itulah mengapa menurut saya Anda perlu mengecualikan item yang Anda klik untuk membuka dialog. Saya tidak mengerti mengapa Anda perlu merujuk tautan dalam dialog?
personne3000
@ personne3000 - sebenarnya Anda benar tentang konteksnya, bahwa pemilih memilih keduanya. Saya mencoba mengingat mengapa saya menambahkannya, karena saya pasti punya alasan khusus yang tidak saya ingat saat ini.
Jason
@Jason untuk menghindari konflik dengan banyak dialog Anda dapat menggunakan peristiwa click.myNamespace
spasi
17

Cukup tambahkan skrip global ini, yang menutup semua dialog modal hanya dengan mengklik di luar sana.

$(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");
            }
        });
    });;
});
Michele Locati
sumber
Saya tidak menggunakan dialog modal. Jawaban di sini dengan suara terbanyak juga untuk dialog modal.
Sonny
Saat menggunakan dialog yang sama lebih dari sekali pada halaman yang sama, ini adalah satu-satunya cara untuk melakukannya karena hanya akan bekerja sekali jika Anda mengikatnya dalam fungsi buka. Terima kasih untuk ide bagus ini!
MaDaHoPe
ini milikku:$(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" );
});

Biola menunjukkan kode di atas beraksi.

jk.
sumber
Saya akan melihatnya. Terima kasih Jen!
Sonny
8

Saya harus melakukan dua bagian. Pertama, penangan klik luar:

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

Ini memanggil kelas dialog('close')generik ui-dialog-content, dan akan menutup semua dialog jika klik tidak berasal dari salah satunya. Ini akan bekerja dengan dialog modal juga, karena overlay bukan bagian dari .ui-dialogkotak.

Masalahnya adalah:

  1. Kebanyakan dialog dibuat karena klik di luar dialog
  2. Penangan ini berjalan setelah klik tersebut membuat dialog dan menggelembung ke dokumen, jadi segera menutupnya.

Untuk memperbaikinya, saya harus menambahkan stopPropagation ke penangan klik tersebut:

moreLink.on('click', function (e) {
    listBox.dialog();
    e.stopPropagation(); //Don't trigger the outside click handler
});
Jerph
sumber
Ini terdengar lebih sederhana daripada solusi yang saya gunakan. Saya harus mencobanya.
Sonny
Ini adalah solusi yang saya pikirkan tentang diri saya sendiri, tetapi solusi saya hanya satu baris:$('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
styfle
5

Pertanyaan ini agak lama, tetapi jika seseorang ingin menutup dialog yang BUKAN modal ketika pengguna mengklik di suatu tempat, Anda dapat menggunakan ini yang saya ambil dari plugin JQuery UI Multiselect . Keuntungan utama adalah klik tidak "hilang" (jika pengguna ingin mengklik link atau tombol, tindakan sudah selesai).

$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');
                        }            
                    });
                }                    
            });
Melanie
sumber
Saya harus pindah ke var $dialog = $(this).dialog('widget');dalam event handler on-click
Stefan Haberl
1
@Melanie, saya pikir solusi Anda lebih dapat diterapkan, daripada yang lain. Seorang pria membuat plugin untuk 'dialog jqui' berdasarkan pendekatan Anda - js di github
resnyanskiy
5

Anda dapat melakukannya tanpa menggunakan plugin tambahan apa pun

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

Di sini $ dialog adalah dialognya. Apa yang pada dasarnya kita lakukan adalah mendapatkan widget overlay terakhir setiap kali dialog ini dibuka dan mengikat handler klik ke overlay itu untuk menutup $ dialog seperti kapan pun overlay diklik.

GuruKay
sumber
Saya rasa ini mirip dengan solusi lain untuk dialog modal. Pertanyaan saya adalah untuk dialog non-modal.
Sonny
5

tidak perlu plugin acara luar ...

cukup tambahkan event handler ke div .ui-widget-overlay:

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

pastikan saja bahwa pemilih apa pun yang Anda gunakan untuk dialog ui jQuery, juga dipanggil untuk menutupnya .. yaitu # ui-dialog-selector-goes-here

Jonathan Marzullo
sumber
Beberapa solusi untuk menutup dialog modal telah diusulkan. Dialog saya non-modal, dan karenanya tidak memiliki hamparan.
Sonny
Daripada Anda cukup mengikat peristiwa klik ke tag badan atau pembungkus div dan menggunakannya sebagai pemicu peristiwa klik Anda, bukan modal.
Jonathan Marzullo
Iya. Pada dasarnya itulah solusi saya. Itu juga harus mengecualikan klik dalam dialog.
Sonny
3

Ini tidak menggunakan jQuery UI, tetapi menggunakan jQuery, dan mungkin berguna bagi mereka yang tidak menggunakan jQuery UI karena alasan apa pun. Lakukan seperti itu:

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

$(document).ready(function(){

  showDialog();    

});

Jadi, setelah saya menampilkan dialog, saya menambahkan handler klik yang hanya mencari klik pertama pada apa pun.

Sekarang, akan lebih baik jika saya bisa membuatnya mengabaikan klik pada apa pun di #dialog dan isinya, tetapi ketika saya mencoba mengganti $ ('*') dengan $ (': not ("# dialog, # dialog *") '), masih mendeteksi #klik dialog.

Bagaimanapun, saya menggunakan ini murni untuk lightbox foto, jadi berfungsi dengan baik untuk tujuan itu.

Volomike
sumber
2

Contoh yang diberikan menggunakan satu dialog dengan id '#dialog', saya membutuhkan solusi yang menutup dialog apa pun:

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

Terima kasih kepada kolega saya Youri Arkesteijn atas saran penggunaan prototipe.

David van der Tuijn
sumber
2

Ini adalah satu-satunya metode yang berhasil untuk saya untuk dialog NON-MODAL saya

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

Semua kredit masuk ke Axle
Click di luar dialog non-modal untuk menutup

Colin
sumber
1

Saya menggunakan solusi ini berdasarkan yang diposting di sini:

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;
}
Alejo
sumber
1

Saya mengalami masalah yang sama saat membuat modal pratinjau di satu halaman. Setelah banyak googling saya menemukan solusi yang sangat berguna ini. Dengan peristiwa dan target, ia memeriksa di mana klik terjadi dan bergantung padanya memicu tindakan atau tidak melakukan apa pun.

Situs Perpustakaan Cuplikan Kode

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

Sederhananya sebenarnya Anda tidak memerlukan plugin apa pun, cukup jquery atau Anda dapat melakukannya dengan javascript sederhana.

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

Saya tidak berpikir menemukan dialog menggunakan $ ('. Any-selector') dari seluruh DOM begitu cerah.

Mencoba

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

Anda benar-benar mendapatkan hamparan dari contoh dialog yang dimilikinya, hal ini tidak akan pernah salah.

anak nakal
sumber
Ini untuk dialog modal? OP saya adalah tentang non-modal, jadi tidak ada overlay.
Sonny
0

Dengan kode berikut, Anda dapat mensimulasikan klik pada tombol 'tutup' dari dialog (ubah string 'MY_DIALOG' untuk nama dialog Anda sendiri)

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

Kode Cerdas: Saya menggunakan kode berikut agar semuanya tetap jelas dan dapat dibaca. tubuh bagian luar akan menutup kotak dialog.

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

function closeDialogBox() {
    $('#dialog-message').dialog('close');
}
Farid Abbas
sumber
0

Saya akhirnya menggunakan kode ini yang seharusnya berfungsi pada setiap dialog terbuka di halaman, mengabaikan klik pada tooltips, dan membersihkan sumber daya dari dialog yang ditutup juga.


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

            }
        });
Kevin Baragona
sumber