Cómo hacer un menú como Stack Overflow’s

Me gusta mucho la forma en que Stack Overflow ha hecho sus menús desplegables en la parte superior. Observe cómo debe hacer clic para que se active el menú desplegable, pero aún debe desplazarse para obtener el menú desplegable. También hay lo que parecen ser grupos: una vez que haga clic, el control deslizante activará los menús que se muestran en la imagen. Es difícil de explicar, pero si juegas por un minuto verás a qué me refiero. Además, es importante que se muestre el último menú suspendido hasta que el usuario vuelva a hacer clic.

Sistema de menú de Stack Overflow

Esto es lo que tengo hasta ahora; Tenga en cuenta que casi tengo la misma funcionalidad, a excepción de que el último menú suspendido no permanece desactivado (se cierra en mouseout cuando no debería hasta que no haga clic) y la funcionalidad de alternar es incompleta:

$(document).ready(function() { var depressed = false; $('.menu').click(function() { depressed = true; $('.menu').toggleClass('active'); }); $('.menu').hover(function() { if (depressed) { $('.menu').toggleClass('active'); } }); }); 
 ul { margin: 0; padding: 0; } ul li { display: inline-block; padding: 10px 20px; background: #333; color: #eee; } ul li.active:hover ul { display: block; } ul li ul { display: none; position: absolute; border: 2px solid #555; } ul li ul li { display: block; } 
  

Mi JS no está cortando git. Entonces, ¿cuál es la mejor manera de hacerlo?

No he echado un vistazo al menú SO, así que no sé cómo lo hicieron. Pero esto parece funcionar bien.

Un clic en uno de los botones abre el menú desplegable.

El menú desplegable no se cierra con un ‘mouseout’, como en el código, sino solo cuando se ubica otro menú. Si se desplaza fuera del área del menú, el último menú permanece abierto.

Al hacer clic en cualquier lugar, se cierra el menú.

Por lo tanto, mostrar el menú no se hace directamente utilizando un elemento pseudo :hover en CSS, sino agregando una clase, que permanece allí incluso cuando se abre el menú. Creo que el resultado neto se comporta bastante cerca de Stack Overflow.

 $(function(){ // The event to handle clicks outside of the menu. This will close the menu. var offEvent = function(event){ $('.menu-bar').removeClass('active'); $(document).off('click', offEvent); }; // The click event on the menu buttons, to toggle 'menu mode' as it were. $(document).on('click', '.menu-bar .menu', function(event){ event.preventDefault(); $('.menu-bar').addClass('active'); $(this).addClass('active'); // Leave menu mode by clicking anywhere of the menu. $(document).on('click', offEvent ); }); // Hover toggles between the dropdowns of the separate menus. $('.menu-bar .menu').hover( function(event){ var $current = $(this); $('.menu').each( function(index, element){ var $element = $(this); if ($element.get(0) == $current.get(0)) { $element.addClass('active'); } else { $element.removeClass('active'); } }); }); }); 
 ul { margin: 0; padding: 0; } ul li { display: inline-block; padding: 10px 20px; background: #333; color: #eee; } ul li ul { display: none; position: absolute; border: 2px solid #555; } ul li ul li { display: block; } .menu .dropdown { display: none; } .menu-bar.active .menu.active .dropdown { display: block; } .menu { display: inline-block; position: relative; border: 1px solid grey; } .menu .dropdown { position: absolute; top: 100%; left: 0; border: 2px solid #555; } 
   
 $(document).ready(function() { $('#M1').click(function() { $('#M1').toggleClass('active'); $('#M2').removeClass('active'); $('#M3').removeClass('active'); }); $('#M2').click(function() { $('#M2').toggleClass('active'); $('#M1').removeClass('active'); $('#M3').removeClass('active'); }); $('#M3').click(function() { $('#M3').toggleClass('active'); $('#M1').removeClass('active'); $('#M2').removeClass('active'); }); }); 
 ul { margin: 0; padding: 0; } ul li { display: inline-block; padding: 10px 20px; background: #333; color: #eee; } ul li.active ul { display: block; } ul li ul { display: none; position: absolute; border: 2px solid #555; } ul li ul li { display: block; }