web-dev-qa-db-fra.com

jQuery UI - Fermer la boîte de dialogue lorsque l'utilisateur clique dessus

J'ai un dialogue jQuery UI qui s'affiche lorsque vous cliquez sur des éléments spécifiques. Je souhaite fermer la boîte de dialogue si un clic survient ailleurs que sur ces éléments déclencheurs ou la boîte de dialogue elle-même.

Voici le code pour ouvrir la boîte de dialogue:

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

Si je ne commente pas la dernière partie, la boîte de dialogue ne s'ouvre jamais. Je suppose que c'est parce que le même clic qui ouvre la boîte de dialogue est en train de la refermer.


Code de travail final
Note: Ceci utilise le événements externes jQuery plugin

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

Découvrez le plugin jQuery Outside Events

Vous permet de:

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

Désolé de faire glisser cela après si longtemps, mais j'ai utilisé le ci-dessous. Des inconvénients? Voir la fonction ouverte ...

$("#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'); 
        }); 
    }
});
153
stumac85

Oubliez utiliser un autre plugin:

Voici 3 méthodes pour fermer une boîte de dialogue jquery UI lorsque vous cliquez en dehors de popin:

Si le dialogue est modal/a une superposition d'arrière-plan: 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');
            })
        }
    });
}); 

Si dialog est non modal Méthode 1: méthode 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');
                        }
                       }
                      );

Dialogue non modal Méthode 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;
          }


  });
76
Jason

Ajoutez simplement ce script global, qui ferme tous les dialogues modaux en cliquant simplement sur leur emplacement.

$(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");
            }
        });
    });;
});
15
Michele Locati
$(".ui-widget-overlay").click (function () {
    $("#dialog-id").dialog( "close" );
});

Fiddle montrant le code ci-dessus en action. 

10
jk.

Je devais faire deux parties. D'abord le gestionnaire de clics extérieur:

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

Ceci appelle dialog('close') sur la classe générique ui-dialog-content et ferme donc les boîtes de dialogue all si le clic ne provient pas d'une seule. Cela fonctionnera également avec les boîtes de dialogue modales, car la superposition ne fait pas partie de la zone .ui-dialog.

Le problème est:

  1. La plupart des boîtes de dialogue sont créées à cause de clics hors d'une boîte de dialogue.
  2. Ce gestionnaire s'exécute après que ces clics aient créé une boîte de dialogue et diffusé dans le document afin qu'il les ferme immédiatement.

Pour résoudre ce problème, j'ai dû ajouter stopPropagation à ces gestionnaires de clics:

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

Vous pouvez le faire sans utiliser de plug-in supplémentaire

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

Ici, $ dialog est le dialogue . Ce que nous faisons en gros, c’est d’obtenir le dernier widget de superposition chaque fois que cette boîte de dialogue est ouverte et de lier un gestionnaire de clic à cette superposition pour fermer $ dialog au moment où vous cliquez sur la superposition.

5
GuruKay

Cette question est un peu ancienne, mais si quelqu'un souhaite fermer une boîte de dialogue qui n'est PAS modale lorsque l'utilisateur clique quelque part, vous pouvez utiliser celle que j'ai tirée du plugin JQuery UI Multiselect . Le principal avantage est que le clic n'est pas "perdu" (si l'utilisateur veut cliquer sur un lien ou un bouton, l'action est terminée). 

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

pas besoin du plugin événements extérieurs ...

ajoutez simplement un gestionnaire d’événements à la div .ui-widget-overlay:

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

assurez-vous simplement que le sélecteur que vous avez utilisé pour la boîte de dialogue jQuery ui est également appelé pour la fermer. c.-à-d. # ui-dialogue-sélecteur-va-ici

5
Jonathan Marzullo

Cela n'utilise pas l'interface utilisateur de jQuery, mais bien jQuery, et peut être utile pour ceux qui n'utilisent pas l'interface utilisateur de jQuery pour une raison quelconque. Faites-le comme ça:

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

$(document).ready(function(){

  showDialog();    

});

Ainsi, une fois que j'ai affiché une boîte de dialogue, j'ai ajouté un gestionnaire de clic qui ne cherche que le premier clic sur quoi que ce soit. 

Maintenant, ce serait mieux si je pouvais le faire pour ignorer les clics sur quoi que ce soit sur #dialog et son contenu, mais quand j'ai essayé de changer $ ('*') avec $ (': not: "(# dialog, # dialog *") '), il a toujours détecté des clics #dialog.

Quoi qu'il en soit, je l'utilisais uniquement pour une lightbox photo, donc cela fonctionnait bien pour cela.

3
Volomike

Les exemples donnés utilisent un dialogue avec l'id '#dialog', j'avais besoin d'une solution qui ferme tout dialogue:

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

Merci à mon collègue Youri Arkesteijn pour la suggestion d'utiliser un prototype.

2

J'ai eu le même problème en rendant l'aperçu modal sur une page. Après beaucoup de recherches sur Google, j'ai trouvé cette solution très utile. Avec event et target, il vérifie où le clic s'est produit et, en fonction de cela, déclenche l'action ou ne fait rien. 

Site de la bibliothèque d'extraits de code

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

Pour ceux que vous êtes intéressés, j'ai créé un plugin générique qui permet de fermer une boîte de dialogue lorsque vous cliquez en dehors de celle-ci, qu'il s'agisse d'une boîte de dialogue modale ou non. Il supporte un ou plusieurs dialogues sur la même page. 

Plus d'informations ici: http://www.coheractio.com/blog/closing-jquery-ui-dialog-widget-when-clicking-outside

Laurent

1
Laurent

J'utilise cette solution basée sur celle publiée ici:

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
Alejo

C'est la seule méthode qui a fonctionné pour moi pour mon dialogue NON-MODAL

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

Tout le mérite revient à Axle 
Cliquez en dehors de la boîte de dialogue non modale pour fermer

1
Versatile

Avec le code suivant, vous pouvez simuler un clic sur le bouton 'fermer' de la boîte de dialogue (changer la chaîne 'MY_DIALOG' pour le nom de votre propre boîte de dialogue)

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

Je ne pense pas que trouver du contenu de dialogue en utilisant $ ('. Any-selector') dans tout le DOM soit si brillant.

Essayer

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

Vous obtenez vraiment la superposition de l'instance de dialogue à laquelle elle appartient, les choses ne se tromperont jamais de cette façon.

0
badboy

Code intelligent: J'utilise le code suivant pour que tout reste clair et lisible.

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

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

C’est simple, en fait, vous n’avez besoin d’aucun plug-in, vous n'avez besoin que de jQuery ou vous pouvez le faire en javascript.

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