web-dev-qa-db-fra.com

Existe-t-il un événement DOM qui se déclenche lorsqu'un élément de sélection HTML est fermé?

Je recherche un événement DOM que je peux écouter avec JavaScript lorsque lorsqu'un élément sélectionné a été ouvert (mais aucune option n'a été modifiée) est fermé en cliquant sur l'élément sélectionné, quelque part (n'importe où) sur la page.

Ce n'est pas l'événement blur de la sélection, car la sélection conserve le focus. De même, ce n'est pas l'événement focus d'un autre élément ou du document, ni un mousedown ou click sur la fenêtre, le document ou le corps.

Ce n'est pas l'événement change de la sélection, car aucune option de la sélection n'a été modifiée.

Je ne m'inquiète pas pour les anciens explorateurs d'Internet, mais simplement pour les navigateurs modernes. Les piratages propriétaires pourraient être utile de savoir cependant.

J'ai créé un JSFiddle pour illustrer le problème: http://jsfiddle.net/premasagar/FpfnM/

  1. Cliquez sur la zone de sélection dans le panneau "Résultat".
  2. Cliquez sur le texte marqué "ICI" (ou n'importe où ailleurs) d'un simple clic pour voir si un événement est ajouté au journal. Il n'y a pas d'événement dans le dernier Chrome ou Firefox.

La question est donc la suivante: Quel code JavaScript pourrait être ajouté pour enregistrer un événement en cliquant sur la case à cocher?

(J'ai posé une question similaire, mais différente, ici:
JavaScript sur iOS: ouvrir un élément de sélection HTML )

51
Premasagar

Malheureusement, il n'y a pas d'événement standard pour savoir quand une boîte de sélection est fermée ou ouverte, votre code va donc être assez poilu avec des adaptations pour différents navigateurs. Cela dit, je pense que cela peut être fait et que quelque chose fonctionne pour vous dans Firefox en utilisant l'événement mouseup:

http://jsfiddle.net/FpfnM/50/

Dans Firefox (et je suppose que Chrome), vous devrez suivre de très près l'état de cette sélection. Lorsqu'une touche escape est enfoncée ou qu'un événement blur se produit, vous devez mettre à jour l'état pour l'identifier comme étant fermé. Je n'ai pas implémenté cela dans ma démo, et vous pouvez voir ce qui se passe si vous appuyez sur échappement au lieu de cliquer sur la sélection.

Les choses étaient plus simples dans Safari, où un événement mousedown sur la sélection signifie l'ouverture de la sélection, et toute fermeture de la sélection est signifiée par un événement click.

Si vous trouvez un navigateur où aucun de ces événements ne se déclenche, vous pouvez essayer une astuce supplémentaire. Comme les widgets de formulaire tels que select et textarea sont souvent restitués par le système d’exploitation et non dans le navigateur, il est possible que vous puissiez interagir avec eux et certains messages risquent de ne pas entrer dans le gestionnaire d’événements du navigateur. Si vous deviez positionner une zone de texte transparente couvrant l’écran sur un indice z inférieur lorsque la zone de sélection est ouverte, vous pourrez peut-être l’utiliser pour suivre ce clic de fermeture. Il peut être capable de capturer des événements qu'un élément DOM du navigateur peut manquer.

Mise à jour: Chrome voit un clic de souris sur la sélection lorsqu'il s'ouvre et une souris sur le document lorsque la page est cliquée avec une sélection ouverte. Voici une version qui fonctionne avec Chrome:

http://jsfiddle.net/FpfnM/51/

Encore une fois, vous aurez besoin de faire une détection de navigateur pour gérer le bon comportement dans chacun. Un problème avec Chrome, en particulier, est qu’aucun événement n’est déclenché lorsque vous cliquez une seconde fois sur le bouton de sélection pour le fermer. Vous pouvez toutefois détecter le clic de la page.

Résumé rapide:

Chrome/Safari: select.mousedown on open, document.mouseup on close
Firefox: select.click on open, document.mouseup on close
IE8/IE7: select.click on open, document.mouseup on close

Il y a énormément de cas Edge pour d'autres événements qui signifient une fermeture (pression sur une touche d'échappement, flou, etc.), mais il s'agit du minimum pour gérer le scénario dans lequel un utilisateur clique sur la zone de sélection, puis clique dans la zone de document. .

J'espère que cela t'aides!

29
Jason Striegel

Lorsque vous avez plus d'un menu déroulant:

        $("select").each(function () {
        var initDropdown = $(this);
        initDropdown.data("open", false);
        console.log(this.name + "   closed");

        initDropdown.on("blur", function () {
            var blurDdopdown = $(this);
            blurDdopdown.data("open", false);
            console.log(this.name + "   closed");
        });
    });

    $("select").bind("click", function () {
        var clickedDropdown = $(this);

        if (clickedDropdown.data('open') == false) {
            clickedDropdown.data('open', true);
            console.log(this.name + "   open");
        } else {
            clickedDropdown.data('open', false);
            console.log(this.name + "   closed");
        }
    });
2
Bogdan

Pour ce faire, mon premier réflexe consiste à utiliser le code que vous utilisez normalement pour fermer un menu déroulant (personnalisé) sur la presse à l’extérieur:

function clickInBody(){
 functionToCallOnBlur();
}

function clickInBodyStop(event){
    event.stopPropagation();
}

Ensuite, sur votre balise body, ajoutez onClick="clickInBody()" et sur votre élément sélectionné, ajoutez onClick="clickInBodyStop(event)". Cela devrait appeler l'événement chaque fois que vous cliquez sur la page, mais si vous cliquez sur la balise select, la propagation sera interrompue et non appelée functionToCallOnBlur().

1
Tomas

J'ai eu les événements suivants en suivant les instructions sur votre JSFiddle à la lettre:

BODY, mousedown, STRONG
#document, mousedown, STRONG
window, mousedown, STRONG
SELECT, blur, SELECT
BODY, click, STRONG
#document, click, STRONG
window, click, STRONG

Ce sont tous les événements qui ont été déclenchés lorsque j'ai cliqué sur "ICI" après que le menu de sélection était déjà actif et développé. C'était dans la dernière version de Chrome.

Est-ce que l'un de ces objectifs ne devrait pas suffire à vos fins?

Edition: si vous voulez vous assurer que votre élément Select perd le focus, définissez une variable Javascript globale, 'selectFocused', et définissez-la sur False. Définissez-le sur True lorsque votre menu Select reçoit le focus et définissez-le sur False lorsque l'un des événements ci-dessus se produit. 'selectFocused' peut maintenant être utilisé n'importe où dans votre code pour déterminer si votre élément Select a actuellement le focus, et lorsqu'il change des valeurs, vous savez que votre élément Select a été sélectionné ou non.

1
sichinumi

condition préalable: utiliser jQuery! Ceci ne résoudra probablement qu'une partie de votre problème, mais si vous recherchez un événement à déclencher lorsque vous cliquez sur un élément, vous pouvez utiliser un div superposé.

Lorsque l'utilisateur clique sur la zone de sélection:

$('#mySelectBox').click(function () {
    var myOverlayDiv = $('<div id="overlayDiv" class="overlayDiv"></div>')
    .click(function () {
        // call your "select lost focus" function here
        // which should include $('#overlayDiv').remove() somewhere!
    })
    .show()
    .appendTo(document.body);
});

Style pour la superposition div:

.overlayDiv {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
opacity:0;
z-index:1000;
}

Vous devez vous assurer que votre menu de sélection est un index Z supérieur. Ainsi, lorsque l'utilisateur clique sur le menu, il obtient le menu et non le calque de superposition :)

1
jbabey

Si nous considérons que cliquer en dehors de la zone de sélection peut être un signal de l'événement de sélection de fin.

Le jQuery suivant peut faire cela. Ici est le code en violon

$(function () {
    let flag = 0;

    $("#selectId").click(function (e) {
        e.stopPropagation();
        if (flag === 0) {
            flag = 1;
            $(document).one("click", function () {
                flag = 0;
                alert("select end");
            });
        }
    });
});

Code HTML:

<select multiple id="selectId">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>

0
yuxin Zhang