jQuery UI - Chiudi la finestra di dialogo quando si fa clic all'esterno


113

Ho una finestra di dialogo dell'interfaccia utente di jQuery che viene visualizzata quando si fa clic su elementi specifici. Vorrei chiudere la finestra di dialogo se si verifica un clic in un punto diverso dagli elementi di attivazione o dalla finestra di dialogo stessa.

Ecco il codice per aprire la finestra di dialogo:

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

Se rimuovo il commento dall'ultima parte, la finestra di dialogo non si apre mai. Presumo sia perché lo stesso clic che apre la finestra di dialogo la chiude di nuovo.


Nota sul codice di lavoro finale
: utilizza il plug-in 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');
    });
});

Risposte:


31

Controlla il plugin jQuery Outside Events

Ti permette di fare:

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

Ottengo lo stesso comportamento, in quanto il suggerimento non viene visualizzato quando si fa clic sugli elementi $ ('. Hint'). Questi elementi sono "fuori" dal dialogo.
Sonny

Ti interessa solo il clic esterno se la finestra di dialogo è aperta. Quindi rilegalo solo dopo averlo aperto.
PetersenDidIt

3
Ho letto in un altro posto sul filtro basato sull'evento e questo ha risolto il problema: groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
Sonny

La finestra di dialogo viene riutilizzata più volte nel documento, quindi dovrei avere un modo per svincolarsi quando si chiude la finestra di dialogo. Penso che il filtraggio sia una soluzione più semplice.
Sonny

159

Mi dispiace trascinare questo dopo così tanto tempo, ma ho usato il seguente. Qualche svantaggio? Vedi la funzione open ...

$("#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
In realtà questo funzionerà solo se la finestra dell'interfaccia utente è modale. Molto utile se vuoi chiudere una finestra di dialogo modale
stumac85

37
Molto bella. L'ho appena cambiato in questo modo quindi non ho dovuto impostare esplicitamente il riferimento ID:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
James McCormack

1
Mi piace questa. C'è un caso in cui non vuoi che sia modale ma vuoi comunque fare clic all'esterno per chiudere? Non ha senso per me (immagino che con il modale perdi il passaggio del mouse sugli elementi esterni / inferiori).
Nick Spacek

3
@ NickSpacek - Quando non è modale posso impostare il focus su un campo, aprire una nuova finestra di dialogo, ecc. Con un solo clic. Con una finestra di dialogo modale dovrei usare due clic: uno per chiuderla e uno per eseguire l'azione successiva.
Sonny

1
Grazie! Puoi anche sfruttare jQuery live bubbling. $ ('body'). on ('click', '.ui-widget-overlay', close);
Quang Van

78

Dimentica di usare un altro plugin:

Ecco 3 metodi per chiudere una finestra di dialogo dell'interfaccia utente jquery quando si fa clic al di fuori del popin:

Se la finestra di dialogo è modale / ha una sovrapposizione di sfondo: 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');
            })
        }
    });
}); 

Se la finestra di dialogo non è modale Metodo 1: metodo 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');
                        }
                       }
                      );

Finestra di dialogo non modale Metodo 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
Grande! Ho leggermente modificato la funzione di opzione di apertura per la finestra di dialogo modale, quindi non è necessario nominare esplicitamente l'elemento. open : function () { $('.ui-widget-overlay').on('click', function () { $(this).parents("body").find(".ui-dialog-content").dialog("close"); }); }
meridius

Nota che per la soluzione n. 2, .is ('. Ui-dialog, a') deve essere cambiato in .is ('. Ui-dialog, anyYouClickOnToOpenTheDialog')
personne3000

@ Jason a causa della virgola, penso che questa riga in realtà stia dicendo "non la ui-dialog, o qualsiasi collegamento nella pagina". Se cambio il collegamento "Apri finestra di dialogo" nel tuo esempio in <span>, la finestra di dialogo viene chiusa immediatamente dopo l'apertura poiché l'evento della finestra viene attivato per ultimo, motivo per cui penso che sia necessario escludere l'elemento su cui fai clic per aprire il dialogo. Non capisco perché dovresti fare riferimento ai link nella finestra di dialogo?
personne3000

@ personne3000 - in realtà hai ragione sul contesto, che il selettore sta scegliendo entrambi. Sto cercando di ricordare perché l'ho aggiunto, poiché devo aver avuto un motivo specifico che non ricordo al momento.
Jason

@ Jason per evitare conflitti con più finestre di dialogo è possibile utilizzare eventi con spazio dei nomiclick.myNamespace
Christophe Roussy

17

Basta aggiungere questo script globale, che chiude tutte le finestre di dialogo modali semplicemente facendo clic all'esterno di esse.

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

Non sto usando una finestra di dialogo modale. La risposta qui con il maggior numero di voti positivi è anche per le finestre di dialogo modali.
Sonny

Quando si utilizza la stessa finestra di dialogo più di una volta sulla stessa pagina, questo è l'unico modo per procedere poiché funzionerà solo una volta se lo si lega nella funzione di apertura. Grazie per questa fantastica idea!
MaDaHoPe

ecco il mio:$(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" );
});

Violino che mostra il codice sopra in azione.


Lo darò un'occhiata. Grazie Jen!
Sonny

8

Ho dovuto fare due parti. Innanzitutto il gestore dei clic esterno:

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

Questo richiama dialog('close')la ui-dialog-contentclasse generica e quindi chiuderà tutte le finestre di dialogo se il clic non ha avuto origine in una. Funzionerà anche con le finestre di dialogo modali, poiché la sovrapposizione non fa parte della .ui-dialogscatola.

Il problema è:

  1. La maggior parte delle finestre di dialogo vengono create a causa di clic all'esterno di una finestra di dialogo
  2. Questo gestore viene eseguito dopo che quei clic hanno creato una finestra di dialogo e si sono aggiunti al documento, quindi li chiude immediatamente.

Per risolvere questo problema, ho dovuto aggiungere stopPropagation a quei gestori di clic:

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

Sembra più semplice della soluzione che sto usando. Dovrò provarlo.
Sonny

Questa è la soluzione che ho pensato a me stesso, ma la mia è una battuta:$('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
stile

5

Questa domanda è un po 'vecchia, ma nel caso in cui qualcuno volesse chiudere una finestra di dialogo NON modale quando l'utente fa clic da qualche parte, puoi usarla che ho preso dal plug-in JQuery UI Multiselect . Il vantaggio principale è che il clic non viene "perso" (se l'utente desidera fare clic su un collegamento o un pulsante, l'azione viene eseguita).

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

Ho dovuto spostarmi var $dialog = $(this).dialog('widget');all'interno del gestore dell'evento al clic
Stefan Haberl

1
@ Melanie, penso che la tua soluzione sia più applicabile di altre. Un ragazzo ha creato un plug-in per 'jqui dialog' basato sul tuo approccio - js su github
resnyanskiy

5

Puoi farlo senza utilizzare alcun plug-in aggiuntivo

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

Qui $ dialog è il dialogo. Quello che stiamo facendo fondamentalmente è ottenere l'ultimo widget di overlay ogni volta che viene aperta questa finestra di dialogo e associare un gestore di clic a tale overlay per chiudere $ dialog ogni volta che si fa clic sull'overlay.


Penso che questo sia simile ad altre soluzioni per un dialogo modale. La mia domanda era per i dialoghi non modali.
Sonny

5

non c'è bisogno del plugin per eventi esterni ...

basta aggiungere un gestore di eventi al div .ui-widget-overlay:

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

assicurati solo che qualunque selettore che hai usato per la finestra di dialogo dell'interfaccia utente di jQuery, sia anche chiamato per chiuderla .. cioè # ui-dialog-selector-va-qui


Sono già state proposte diverse soluzioni per chiudere le finestre di dialogo modali. La mia finestra di dialogo non è modale e quindi non ha alcuna sovrapposizione.
Sonny

Quindi associ semplicemente l'evento clic al tag body o al wrapper div e usalo come attivatore dell'evento clic, invece del modale.
Jonathan Marzullo

Sì. Questo è essenzialmente ciò che fa la mia soluzione. Deve anche escludere i clic all'interno della finestra di dialogo.
Sonny

3

Questo non utilizza jQuery UI, ma utilizza jQuery e può essere utile per coloro che non utilizzano jQuery UI per qualsiasi motivo. Fallo così:

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

$(document).ready(function(){

  showDialog();    

});

Quindi, una volta visualizzata una finestra di dialogo, aggiungo un gestore di clic che cerca solo il primo clic su qualsiasi cosa.

Ora, sarebbe più bello se potessi far sì che ignori i clic su qualsiasi cosa su #dialog e sui suoi contenuti, ma quando ho provato a cambiare $ ('*') con $ (': not ("# dialog, # dialog *") '), ha comunque rilevato # clic di dialogo.

Ad ogni modo, lo stavo usando esclusivamente per un lightbox fotografico, quindi ha funzionato bene per quello scopo.


2

Gli esempi forniti utilizzano una finestra di dialogo con id '#dialog', avevo bisogno di una soluzione che chiudesse qualsiasi finestra di dialogo:

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

Grazie al mio collega Youri Arkesteijn per il suggerimento di utilizzare il prototipo.


2

Questo è l'unico metodo che ha funzionato per me per la mia finestra di dialogo NON MODALE

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

Tutto il merito va a Fare clic sull'asse
fuori dalla finestra di dialogo non modale per chiudere



1

Uso questa soluzione basata su quella pubblicata qui:

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

Ho avuto lo stesso problema durante la creazione dell'anteprima modale su una pagina. Dopo molte ricerche su Google ho trovato questa soluzione molto utile. Con evento e target, controlla dove è avvenuto il clic e, a seconda di esso, attiva l'azione o non fa nulla.

Sito della libreria di frammenti di codice

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

È semplice in realtà non hai bisogno di plugin, solo jquery o puoi farlo con un semplice javascript.

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

0

Non penso che trovare elementi di dialogo usando $ ('. Any-selector') dall'intero DOM sia così brillante.

Provare

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

Stai davvero ottenendo la sovrapposizione dall'istanza di dialogo a cui appartiene, le cose non andranno mai storte in questo modo.


Questo è per una finestra di dialogo modale? Il mio OP non è modale, quindi non c'è overlay.
Sonny

0

Con il codice seguente, puoi simulare un clic sul pulsante 'chiudi' della finestra di dialogo (cambia la stringa 'MY_DIALOG' per il nome della tua finestra di dialogo)

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

0

Codice intelligente: sto usando il seguente codice in modo che ogni cosa rimanga chiara e leggibile. out side body chiuderà la finestra di dialogo.

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

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

0

Ho finito per utilizzare questo codice che dovrebbe funzionare su tutte le finestre di dialogo aperte nella pagina, ignora i clic sui suggerimenti e ripulisce anche le risorse della finestra di dialogo che viene chiusa.


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

            }
        });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.