jQuery-Benutzeroberfläche - Dialogfeld schließen, wenn außerhalb geklickt wird

113

Ich habe ein jQuery-UI-Dialogfeld, das angezeigt wird, wenn auf bestimmte Elemente geklickt wird. Ich möchte den Dialog schließen, wenn ein Klick irgendwo anders als auf diesen auslösenden Elementen oder im Dialog selbst auftritt.

Hier ist der Code zum Öffnen des Dialogs:

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

Wenn ich den letzten Teil auskommentiere, wird der Dialog nie geöffnet. Ich gehe davon aus, dass derselbe Klick, der den Dialog öffnet, ihn wieder schließt.


Endgültiger Arbeitscode
Hinweis: Hierbei wird das jQuery- Plugin für externe Ereignisse verwendet

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

Antworten:

31

Schauen Sie sich das Plugin jQuery Outside Events an

Lass dich machen:

$field_hint.bind('clickoutside',function(){
    $field_hint.dialog('close');
});
PetersenDidIt
quelle
Ich habe das gleiche Verhalten, da der Hinweis nicht angezeigt wird, wenn auf die Elemente $ ('. Hinweis') geklickt wird. Diese Elemente befinden sich außerhalb des Dialogfelds.
Sonny
Der Klick nach draußen ist Ihnen nur wichtig, wenn der Dialog geöffnet ist. Binden Sie es also erst, nachdem Sie es geöffnet haben.
PetersenDidIt
3
Ich habe an einer anderen Stelle über das Filtern basierend auf dem Ereignis gelesen, und das hat das Problem gelöst: groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
Sonny
Der Dialog wird im Dokument mehrmals wiederverwendet, sodass ich beim Schließen des Dialogs eine Möglichkeit zum Aufheben der Bindung haben muss. Ich denke, die Filterung ist eine einfachere Lösung.
Sonny
159

Es tut mir leid, das nach so langer Zeit nach oben zu ziehen, aber ich habe das Folgende verwendet. Irgendwelche Nachteile? Siehe die Öffnungsfunktion ...

$("#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
quelle
18
Tatsächlich funktioniert dies nur, wenn das UI-Fenster modal ist. Gut nützlich, wenn Sie einen modalen Dialog schließen
möchten
37
Sehr schön. Ich habe es einfach so geändert, damit ich die ID-Referenz nicht explizit $('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
James McCormack
1
Ich mag diesen. Gibt es einen Fall, in dem Sie nicht möchten, dass es modal ist, aber dennoch nach draußen klicken möchten, um es zu schließen? Macht für mich keinen Sinn (ich denke, mit Modal verlierst du das Schweben auf äußeren / unteren Elementen).
Nick Spacek
3
@NickSpacek - Wenn es nicht modal ist, kann ich mit nur einem Klick den Fokus auf ein Feld setzen, ein neues Dialogfeld öffnen usw. Bei einem modalen Dialog müsste ich zwei Klicks verwenden: einen zum Schließen und einen zum Ausführen der nächsten Aktion.
Sonny
1
Vielen Dank! Sie können auch jQuery Live Bubbling nutzen. $ ('body'). on ('click', '.ui-widget-overlay', close);
Quang Van
78

Vergessen Sie die Verwendung eines anderen Plugins:

Hier sind 3 Methoden, um ein jquery-UI-Dialogfeld zu schließen, wenn Sie außerhalb des Popins klicken:

Wenn der Dialog modal ist / Hintergrundüberlagerung hat: 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');
            })
        }
    });
}); 

Wenn der Dialog nicht modal ist Methode 1: Methode 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');
                        }
                       }
                      );

Nichtmodaler Dialog Methode 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
quelle
2
Toll! Ich habe die Funktion zum Öffnen von Optionen für den modalen Dialog geringfügig geändert, sodass das Element nicht explizit benannt werden muss. open : function () { $('.ui-widget-overlay').on('click', function () { $(this).parents("body").find(".ui-dialog-content").dialog("close"); }); }
Meridius
Beachten Sie, dass für Lösung 2 .is ('. UI-dialog, a') in .is ('. UI-dialog, was auch immer Sie anklickenOnToOpenTheDialog') geändert werden muss
personne3000
@ Jason wegen des Kommas, ich denke, diese Zeile sagt tatsächlich "nicht der UI-Dialog oder irgendein Link auf der Seite". Wenn ich den Link "Dialog öffnen" in Ihrem Beispiel in einen <span> ändere, wird der Dialog sofort nach dem Öffnen geschlossen, da das Fensterereignis zuletzt ausgelöst wird. Aus diesem Grund müssen Sie meines Erachtens das Element ausschließen, auf das Sie klicken, um das zu öffnen Dialog. Ich verstehe nicht, warum Sie im Dialog auf Links verweisen müssen?
personne3000
@ personne3000 - eigentlich hast du recht mit dem Kontext, dass der Selektor beide auswählt. Ich versuche mich zu erinnern, warum ich das hinzugefügt habe, da ich einen bestimmten Grund gehabt haben muss, an den ich mich im Moment nicht erinnere.
Jason
@ Jason Um Konflikte mit mehreren Dialogen zu vermeiden, können Sie Ereignisse mit Namensraum verwendenclick.myNamespace
Christophe Roussy
17

Fügen Sie einfach dieses globale Skript hinzu, das alle modalen Dialoge schließt, indem Sie auf sie klicken.

$(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
quelle
Ich verwende keinen modalen Dialog. Die Antwort hier mit den meisten Stimmen ist auch für modale Dialoge.
Sonny
Wenn Sie denselben Dialog mehrmals auf derselben Seite verwenden, ist dies der einzige Weg, da er nur einmal funktioniert, wenn Sie ihn in der Öffnungsfunktion binden. Danke für diese tolle Idee!
MaDaHoPe
Hier ist meins:$(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" );
});

Geige zeigt den obigen Code in Aktion.

jk.
quelle
Ich werde es mir ansehen. Danke Jen!
Sonny
8

Ich musste zwei Teile machen. Zuerst der externe Click-Handler:

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

Dies ruft dialog('close')die generische ui-dialog-contentKlasse auf und schließt so alle Dialoge, wenn der Klick nicht von einem stammt. Es funktioniert auch mit modalen Dialogen, da die Überlagerung nicht Teil der .ui-dialogBox ist.

Das Problem ist:

  1. Die meisten Dialoge werden aufgrund von Klicks außerhalb eines Dialogfelds erstellt
  2. Dieser Handler wird ausgeführt, nachdem diese Klicks einen Dialog erstellt und zum Dokument gesprudelt haben, sodass er sie sofort schließt.

Um dies zu beheben, musste ich diesen Klick-Handlern stopPropagation hinzufügen:

moreLink.on('click', function (e) {
    listBox.dialog();
    e.stopPropagation(); //Don't trigger the outside click handler
});
Jerph
quelle
Das klingt einfacher als die Lösung, die ich verwende. Ich werde es ausprobieren müssen.
Sonny
Dies ist die Lösung, die ich von mir selbst gedacht habe, aber meine ist ein $('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
Einzeiler
5

Diese Frage ist etwas alt, aber falls jemand einen Dialog schließen möchte, der NICHT modal ist, wenn der Benutzer irgendwo klickt, können Sie diese verwenden, die ich aus dem JQuery UI Multiselect-Plugin übernommen habe . Der Hauptvorteil ist, dass der Klick nicht "verloren" geht (wenn der Benutzer auf einen Link oder eine Schaltfläche klicken möchte, wird die Aktion ausgeführt).

$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
quelle
Ich musste mich var $dialog = $(this).dialog('widget');innerhalb des On-Click-Event-Handlers bewegen
Stefan Haberl
1
@ Melanie, ich denke, Ihre Lösung ist anwendbarer als andere. Ein Typ hat ein Plugin für 'jqui dialog' basierend auf Ihrem Ansatz erstellt - js at github
resnyanskiy
5

Sie können dies ohne zusätzliches Plug-In tun

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

Hier ist $ dialog der Dialog. Grundsätzlich rufen wir das letzte Overlay-Widget auf, wenn dieses Dialogfeld geöffnet wird, und binden einen Klick-Handler an dieses Overlay, um das $ -Dialogfeld zu schließen, sobald auf das Overlay geklickt wird.

GuruKay
quelle
Ich denke, dies ähnelt anderen Lösungen für einen modalen Dialog. Meine Frage war für nicht modale Dialoge.
Sonny
5

Das Plugin für externe Ereignisse ist nicht erforderlich ...

Fügen Sie einfach einen Ereignishandler zum .ui-Widget-Overlay-Div hinzu:

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

Stellen Sie einfach sicher, dass der für den jQuery-UI-Dialog verwendete Selektor auch aufgerufen wird, um ihn zu schließen. Das heißt, # ui-dialog-selector-goes-here

Jonathan Marzullo
quelle
Es wurden bereits mehrere Lösungen zum Schließen modaler Dialoge vorgeschlagen. Mein Dialog ist nicht modal und hat daher keine Überlagerung.
Sonny
Dann binden Sie einfach das Klickereignis an das Body-Tag oder den Div-Wrapper und verwenden dieses als Auslöser für das Klickereignis anstelle des Modals.
Jonathan Marzullo
Ja. Genau das macht meine Lösung. Es muss auch Klicks innerhalb des Dialogfelds ausschließen.
Sonny
3

Dies verwendet nicht die jQuery-Benutzeroberfläche, sondern jQuery und kann für diejenigen nützlich sein, die die jQuery-Benutzeroberfläche aus irgendeinem Grund nicht verwenden. Mach es so:

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

$(document).ready(function(){

  showDialog();    

});

Sobald ich ein Dialogfeld angezeigt habe, füge ich einen Klick-Handler hinzu, der nur nach dem ersten Klick auf etwas sucht.

Jetzt wäre es schöner, wenn ich es dazu bringen könnte, Klicks auf irgendetwas in #dialog und dessen Inhalt zu ignorieren, aber als ich versuchte, $ ('*') durch $ (': not ("# dialog, # dialog *") zu wechseln '), es wurden immer noch #dialog-Klicks erkannt.

Wie auch immer, ich habe dies nur für einen Foto-Leuchtkasten verwendet, also hat es für diesen Zweck in Ordnung funktioniert.

Volomike
quelle
2

Die angegebenen Beispiele verwenden einen Dialog mit der ID '#dialog'. Ich brauchte eine Lösung, die jeden Dialog schließt:

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

Vielen Dank an meinen Kollegen Youri Arkesteijn für den Vorschlag, einen Prototyp zu verwenden.

David van der Tuijn
quelle
2

Dies ist die einzige Methode, die für mich in meinem NICHT-MODAL-Dialog funktioniert hat

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

Das gesamte Guthaben geht an Axle.
Klicken Sie zum Schließen außerhalb des nicht modalen Dialogfelds

Colin
quelle
1

Ich verwende diese Lösung basierend auf einer hier veröffentlichten:

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
quelle
1

Ich hatte das gleiche Problem, als ich die Vorschau auf einer Seite modal machte. Nach vielem googeln fand ich diese sehr nützliche Lösung. Mit Ereignis und Ziel wird überprüft, wo das Klicken stattgefunden hat, und abhängig davon wird die Aktion ausgelöst oder es wird nichts unternommen.

Code Snippet Library Site

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

Es ist ganz einfach, eigentlich brauchst du keine Plugins, nur jquery oder du kannst es mit einfachem Javascript machen.

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

Ich denke nicht, dass es so hell ist, Dialogmaterial mit $ ('. Any-selector') aus dem gesamten DOM zu finden.

Versuchen

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

Sie erhalten das Overlay wirklich von der Dialoginstanz, zu der es gehört. Auf diese Weise wird nichts schief gehen.

böser Bub
quelle
Dies ist für einen modalen Dialog? Mein OP ist nicht modal, es gibt also keine Überlagerung.
Sonny
0

Mit dem folgenden Code können Sie einen Klick auf die Schaltfläche "Schließen" des Dialogfelds simulieren (ändern Sie die Zeichenfolge "MY_DIALOG" für den Namen Ihres eigenen Dialogfelds).

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

Smart Code: Ich verwende folgenden Code, damit alles klar und lesbar bleibt. out side body schließt das Dialogfeld.

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

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

Am Ende habe ich diesen Code verwendet, der für alle geöffneten Dialoge auf der Seite funktionieren sollte, Klicks auf QuickInfos ignoriert und die Ressourcen des zu schließenden Dialogs bereinigt.


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