Question Corps Javascript OnClick


Je suis en train d'apprendre le Javascript et j'essaie de créer un simple menu déroulant. Un exemple de ma fonctionnalité désirée peut être vu sur la page d'accueil de Google dans le menu supérieur avec le menu déroulant "plus" et "paramètres". Plus précisément, lorsque vous cliquez sur le menu, le menu disparaît.

Quel code dois-je placer dans la fonction hideMenus de Javascript pour masquer les uls visibles lorsqu'un clic se produit n'importe où sur l'écran?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml">  

<head>  
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />  
<title>Untitled 1</title>  

<style type="text/css">  
a  
{  
    color:blue;  
}  

.info ul.submenu  
{  
    border: solid 1px #e0e0e0;  
    background-color: #fff;  
    position: absolute;  
    padding: 0;  
    z-index: 2;  
    display: none;  
}  

.info ul.submenu li  
{  
    display: block;  
    border-top: solid 1px #e0e0e0;  
    margin: 0px 10px 0 10px;  
}  

.info ul.submenu li a  
{  
    display: block;  
    padding: 7px 0px 6px 0;  
    color: #1177ee;  
    cursor:pointer;  
}  

</style>  

<script type="text/javascript">  

function hideMenus()
{
//TODO
}

function menu(id) {     
    var myLayer = document.getElementById(id);     

    myLayer.onblur = function() {       
        myLayer.style.display = 'none';   
    };   

    if (myLayer.style.display == "none" || myLayer.style.display == "") {     
        myLayer.style.display = "block";     
    } else {     
        myLayer.style.display = "none";     
    }     
}  

</script>  
</head>  

<body onclick="hideMenus();">  
<div class="info">     
     Some Text Boom A <a  onclick="menu('id1');">Link</a> | More text    
     <a onclick="menu('id2');">Another Link</a> | more text    
     <ul id="id1" class="submenu">     
       <li><a href="dfhdfh">A1</a></li>     
       <li><a href="aetjetjsd">A2 This is Long</a></li>     
       <li><a href="etetueb">A3</a></li>     
     </ul>     
    <ul id="id2" class="submenu">     
       <li><a href="dfhdfh">B1</a></li>     
       <li><a href="aetjetjsd">B2</a></li>     
       <li><a href="etetueb">B3</a></li>     
     </ul>     
  </div>    
</body>  
</html>   

Je ne veux pas utiliser jQuery.


10
2017-08-19 11:55


origine


Réponses:


On dirait que vous avez une configuration assez décente telle quelle. Vous rencontrerez probablement des problèmes d’événement (pour plus d’informations, consultez Article de commande d'événement de PPK). Cela semble sortir du cadre de votre question actuelle, alors je vais vous donner ce que vous avez demandé:

hideMenus()
{
    var uls = document.getElementsByTagName('ul'), i;
    for (i = 0; i < uls.length; i++)
    {
        if (uls[i].className === 'submenu' && uls[i].style.display !== 'none')
        {
            uls[i].style.display = 'none';
        }
    }
}

Tout d'abord, nous obtenons tous les <ul> sur la page. Ensuite, nous les parcourons en boucle, vérifiez si c'est un sous-menu et s'il est actuellement affiché. Si les deux sont vrais, alors nous le cachons.

Il y a quelques défauts avec ce code:

  • Si les uls ont plus d'une classe (class="animal submenu"), alors il ne va pas cacher le menu
  • Il va regarder à travers tout les <ul> sur la page. Ce n'est pas tout à fait efficace, mais c'est le seul moyen de le faire sans la prise en charge de plusieurs navigateurs. getElementsByClass.

Ce ne sont pas des défauts énormes, surtout si vous ne l'utilisez que pour apprendre le javascript, et si vous contrôlez étroitement votre code (c'est-à-dire qu'aucun autre développeur n'y travaille). Dans l'ensemble, c'est un bon tremplin.

Dans le futur, je suggère d'utiliser addEvent - une fonction assez courante qui vous permet d'ajouter des gestionnaires d'événements aux éléments sans utiliser onclick="...". Il en existe plusieurs implémentations différentes, mais elles fonctionnent (presque) toutes de la même manière de votre point de vue. Voici des liens vers Version de Dean Edwards et Version de John Resig

Bonne chance!


1
2017-08-19 12:42



Voici plus ou moins la logique que nous utilisons dans notre application Web pour les menus déroulants:

<html>
<head>
    <title></title>
</head>
<body>
    <div style="position:relative;width:250px">
      <a id="link" href="javascript:" onclick="showDiv(this)">Show menu</a>
      <ul id="entries" style="display:none;background:#DEF;padding:0;margin:0">
        <li>item 1</li>
        <li>item 2</li>
      </ul>
      <input id="inp" style="position:absolute;left:-30px;width:0" />
    </div>

    <script>
        function showDiv(lnk){
            var entries = document.getElementById('entries'),
                inp = document.getElementById('inp'),
                nh = 'data-nohide';
            //show the entries
            entries.style.display = 'block';
            entries.removeAttribute(nh);
            inp.focus();
            //if mouse over, can't close it
            entries.onmouseover = function(){ 
                this.setAttribute(nh, true);
                inp.focus();
            }; 
            //if mouse out, can close it
            entries.onmouseout  = function(){ 
                this.removeAttribute(nh);
            };
            entries.onclick = function(e){
                //code when the user clicks on the menu...
                alert((e.target||e.sourceElement).innerHTML);
                this.style.display = 'none';
            };
            //if the user press ESC
            inp.onkeyup = function(e){
                if(e.keyCode === 27){
                    this.style.display = 'none';
                    this.removeAttribute(nh);
                }else{
                    //do something else with other keys(ie:down, up, enter)...
                    inp.focus();
                }
            };
            //click somewhere else input onblur
            inp.onblur = function(){
                if(!entries.getAttribute(nh)){
                    entries.style.display = 'none';
                    entries = inp = null;
                }
            };
        }
    </script>
</body>
</html>

L'astuce consiste à utiliser un input champ qui a le focus, et quand il perd un onblur est déclenché et ferme le menu.

le mouseover, mouseout sont là pour empêcher le onblur tirer lorsque l'utilisateur clique sur un élément du menu.

Pour avoir un effet de bascule comme un open / close sur le lien, je suppose que 2 liens qui se cachent sont nécessaires.


0
2017-08-19 19:42



Vous pouvez capturer un clic n'importe où si vous cliquez sur le corps. En raison du modèle de propagation d'événement javascript, si vous cliquez n'importe où sur un élément et que vous n'arrêtez pas la propagation de l'événement, il atteindra le corps et masquera les menus.

Donc, fondamentalement, cela signifie que vous voulez capturer le corps sur un clic et faire en sorte que les menus soient masqués. Lorsque vous cliquez sur une zone de la page, cela ferme les menus.

Mais cela cache un peu de comportement indésirable - lorsque vous cliquez sur le bouton pour afficher le menu, le menu s’affiche rapidement et après celui-ci (lorsque l’événement atteint le corps). Pour éviter cela, vous devez arrêter la propagation de l'événement lorsque vous cliquez sur le bouton qui affiche le menu (vous pouvez voir comment cela fonctionne dans le code que j'ai posté ci-dessous). Le code montre où vous devez toucher pour le faire fonctionner correctement.

// this function stops event e or window.event if e is not present from 
// propagating to other elements.
function stop_event(e) {
   if(!e) {
      e = window.event;
   }
   if (e.stopPropagation) e.stopPropagation();
   e.cancelBubble = true;
   if (e.preventDefault) e.preventDefault();
   e.returnValue = false;
   return false;
}

// now you just hide all the menus in your hideMenus
function hideMenus()
{
    //pseudocode!
    for all visible menus - hide // or if you want you can hide all menus, 
                                 // the hidden will remain hidden
}

Maintenant, la partie importante.

function menu(id) {     
    // your stuff here
    stop_event(); // this will stop the event going down to the body 
                  // and hiding it after showing it
                  // this means it will not flicker like: show-hide
}  

Et enfin sur tout votre élément UL:

//partly pesudocode
ul.onclick = function() { stop_event(); }

Pour expliquer à nouveau ce que cela fait:

1er Vous connectez votre fonction hideMenu à body.onclick. Cela signifie qu'il masquera toujours les menus si nous n'arrêtons pas l'événement.

2ème Lorsque vous cliquez sur le bouton de menu, vous affichez le menu, puis nous empêchons l’événement d’atteindre le corps. De cette façon, le body.onclick ne se déclenche pas et il ne cache pas le menu juste après l'avoir ouvert.

3ème Le ul.onclick signifie que le menu ne se cachera pas lorsque nous cliquons dessus (mais si vous voulez que le menu se cache lorsque vous cliquez sur le menu lui-même, vous pouvez supprimer cette partie).


-1
2017-08-19 12:21