2016-08-08 8 views
1

Ich erstelle eine zusätzliche Registerkarte in einem Menü dynamisch (nennen wir diese neue Registerkarte, Watch), und alles lief ziemlich gut einschließlich des Untermenüs, das angezeigt wurde, sobald der neue Tab über schwebte. Ich schaute mir Artikel über Event-Sprudeln an und warf einen Blick auf andere Beispiele, fand aber keine Lösung für mein Problem.JavaScript-Untermenü nicht beibehalten

Immer wenn ich über Watch wache, erscheint das Untermenü, aber wenn ich versuche, von Watch zu seinem Untermenü zu schweben, verschwindet das Untermenü. Ich brauche das Untermenü, um fortzufahren, wenn ein Benutzer über Watch oder das Untermenü schwebt, und das Untermenü sollte nur verschwinden, sobald der Benutzer sich von beiden bewegt. Nur zu erwähnen, kann ich CSS für meine Lösung nicht verwenden. Ich habe meinen aktuellen Code unten angehängt mit Kommentaren:

//PREPEND AS FIRST CHILD 
var prependChild = function(parent, newFirstChild) { 
    parent.insertBefore(newFirstChild, parent.firstChild) 
} 

//DECLARING VARS 
var navMenu    = document.getElementsByClassName('navGlobal-list')[0]; 
    categoryExplorer  = document.getElementsByClassName('categoryExplorer')[0]; 

//CREATING NEW TAB 
var exploreTab   = document.createElement('li'); 
    exploreTab.className = 'navGlobal-category'; 

//CREATING NEW SEARCH FORM 
var searchHtml = ['<div class="searchProgram searchProgram--categoryExplorer">', 
         '<div class="searchProgram-container">', 
          '<input type="search" class="form-control form-control--light form-control--searchProgram" placeholder="Search programs" value="">', 
         '</div>', 
        '</div>'].join(''); 

//CREATING NEW WATCH CATEGORY EXPLORER CONTENT  
var watchCategoryExplorerContent = document.createElement('div'); 
    watchCategoryExplorerContent.className = 'categoryExplorer-content target-watch-content'; 
    watchCategoryExplorerContent.innerHTML = searchHtml; 
    prependChild(categoryExplorer, watchCategoryExplorerContent) 

var watchLink = document.createElement('a');  
    watchLink.setAttribute('href','/watch'); 
    watchLink.innerHTML = 'watch'.toUpperCase();  

exploreTab.appendChild(watchLink); 
navMenu.appendChild(exploreTab); //ADDED 'WATCH' TO THE NAVIGATION 

//CHANGE CLASSES ON HOVER 
exploreTab.addEventListener("mouseover", function() { 
    exploreTab.className = 'navGlobal-category navGlobal-category--open'; 
    categoryExplorer.className = 'categoryExplorer categoryExplorer--open'; 
    watchCategoryExplorerContent.className = 'categoryExplorer-content categoryExplorer-content--open target-watch-content'; 
}, false); 

exploreTab.addEventListener("mouseleave", function() { 
    exploreTab.className = 'navGlobal-category'; 
    categoryExplorer.className = 'categoryExplorer'; 
    watchCategoryExplorerContent.className = 'categoryExplorer-content target-watch-content'; 
}, false); 

Antwort

2

Ein Potential (Layout abhängig) Art und Weise das Menü offen zu halten, wäre es ein Kind des Registerkarte zu machen - diese Weise, vorausgesetzt, es keinen Raum zwischen der Registerkarte und dem Hover-Menü können Sie von einem Punkt zum anderen wechseln, ohne ein mouseleave-Ereignis auf der Registerkarte zu erstellen.

Eine andere Lösung, die nicht Layout-abhängig ist, wäre eine gewisse Verzögerung zwischen dem anfänglichen mouseleave-Ereignis und dem Schließen des Untermenüs hinzuzufügen. Ich habe so etwas zuvor mit jQuery gemacht, aber dasselbe sollte ohne es möglich sein.

$('.navGlobal-category').mouseleave(function(){ 
    setTimeout(
    function(){ 
     if(!isHovered($('.navGlobal-category')[0])){ 
     exploreTab.className = 'navGlobal-category'; 
     categoryExplorer.className = 'categoryExplorer'; 
     watchCategoryExplorerContent.className = 'categoryExplorer-content target-watch-content'; 
     } 
    }, 200); 
}); 

function isHovered(e){ 
    return ((e.parentNode.querySelector(":hover") || 
    e.querySelector(":hover")) === e); 
} 

Kredit ‚für die isHovered Lösung zb: https://stackoverflow.com/a/14800287/5403341

2

Für das Nicht-Layout Lösung @ B1SeeMore empfehlen Sie eigentlich keine Verzögerung benötigen.

Hier ist ein funktionierendes Demo: https://jsfiddle.net/jw22ddzk/

<div id="one" class="menuitem"></div> 
<div id="two" class="menuitem" style="display: none;"></div> 

var elems = document.getElementsByClassName("menuitem"); 
for (var i = 0; i < elems.length; i += 1) { 
    elems[i].addEventListener("mouseleave", function() { 
    console.log("leave", this.id); 
    document.getElementById("two").style.display = "none"; 
    }); 
    elems[i].addEventListener("mouseenter", function() { 
    console.log("enter", this.id); 
    document.getElementById("two").style.display = ""; 
    }); 
} 

Der Trick ist, dass mouseenter Feuer für two auch wenn mouseleave das Element verbirgt. Denken Sie daran, das Element erneut zu zeigen. Eine ähnliche Erklärung ist, dass die mouseenter und mouseleave Ereignisse in Paaren spawnen. So passiert mouseenter unabhängig von den Auswirkungen von mouseleave.

Beachten Sie, dass dies nur funktioniert, wenn die Elemente pixelgenau nebeneinander liegen.


Noch ein Hinweis: Ich stelle fest, dass Sie mouseover und mouseleave verwenden. Ich würde das nicht empfehlen. Es gibt zwei Ereignispaare zum Erkennen von Hovern: mouseenter/leave und mouseover/out. Sie sind verschiedene Ereignisse. Sie unterscheiden sich speziell dadurch, dass mouseover/out auch für Kinder ausgelöst wird. Meine Empfehlung ist, dass Sie die Paare nicht austauschen oder Sie unerwartetes Verhalten erhalten.

+0

Es scheint, dass die Anzeige ändert sich nicht das Untermenü zeigt, und dass der einzige Weg, das Menü zeigt, wenn die Klassen, categoryExplorer - offen, navGlobal-Kategorie - offen und categoryExplorer-Inhalt - offen vorhanden sind - ist gibt es einen Weg um dies, das Display nicht einstellen würde? –

+0

Das ist seltsam für sich. Gibt es da ein "Wichtiges"? Ich verstehe nicht wirklich, wie Sie Ihre Klassen verwenden. Sie sind für mich nicht intuitiv und ohne die Definition zu sehen, verstehe ich sie nicht. – Halcyon

+0

Es ist in Ordnung, ich habe das Menü als einen Ansatz ersetzt und arbeite an einem anderen Ansatz ohne den Mauszeiger. Das Layout wird gebaut aus Reagieren und das Untermenü nur zeigte basierend darauf, ob Klassen bestanden oder nicht auf einem separaten Bauteil. –

Verwandte Themen