Ayuda con javascript

Iniciado por V0LT4GE, 15 Noviembre 2021, 21:12 PM

0 Miembros y 1 Visitante están viendo este tema.

V0LT4GE

Estoy haciendo una pagina web, donde el diseño para celular, tiene una barra de navegacion.
Quiero que dicha barra de navegacion se cierre al momento de hacer click en cualquier parte de la pantalla que no sea el contenedor de dicha barra, ya intente varias cosas y nada sale, el problema es que intento hacer un "if" para que solo funcione el click y remueva la clase para hacer desaparecer la barra cuando contenga la clase "show-menu"(esa es la clase que se añade para que se muestre el menu) pero no entra el if  y no se porque 





const navToggle = document.querySelector('.nav_toggle'),
nav = document.querySelector('.nav_list')


/* Validate if constant exists */

if(navToggle){
    navToggle.addEventListener('click', () =>{
        nav.classList.add('show-menu')
        navToggle.classList.add('show-menu')
    })
} else if(navToggle.classList.contains('.show-menu')){
    document.addEventListener('click' , () =>{
        nav.classList.remove('show-menu')
        navToggle.classList.remove('show-menu1')
    })
}





el primer if si entra, el que valida si existe la constante "navToggle" (que es el icono para hacer aparecer la barra) el problema es que el segundo if no entra, ya intente con else, con otro if, con else if, y nada funciona, alguna recomendacion de como hacer que funcione?


@XSStringManolo

No es buena idea añadir listeners cuando se cumpla una condición. En código donde en distintos momentos se cumpla una u otra, si no eliminas el listemer anterior y simplemente añades uno nuevo, se te van a acumular el listener antiguo y el nuevo.

Una de las principales diferncias entre nav.addEventListener("click" callback), y nav.onclick, es que uno añade eventos y el otro settea un evento. Es decir, de la segunda forma se eliminan todos los eventos que exisitían antes. Dependiendo del código puedes optar por el onclick o en su defecto por removeEventListener (por ejemplo cuando tienes 3 eventos, y solo quieres eliminar uno y no todos)

Tu condición está mal, dices:
Si (nav) {
  Haz
} en caso contrario (nav.propiedad.otra propiedad) {

}

Si no existe toggle, te vas a tu else if, en el cual intentas acceder a una propiedad de toggle que 100% no existe. Aún por encima accedes a las propiedades sin saber si exite toggle sin usar el interrogante.
Cuando no está claro si un elemento es inexistente, tira error al acceder a sus propiedades. En todo caso seria else if(nav?.propiedad?.otraPropiedad)

También es posible que quieras capurar el click en toda la página, ya que lo que pretendes es hacer desaparecer el nav cuando se haga click fuera del nav. Para ello tienes que añadir el listener a window.

Otro problema que veo es con los hijos de nav. Si tienes hijos en el nav que están por encima del nav, al hacerle click al hijo, no te salta el evento del nav (porque le haces click al hijo y no al nav directamente. Tienes que propagar el evento de hijo a padre. Es una opción de addEventListener. Si miras en la documentación de MDN de addEventListener, te explican en detalle como hacerlo y como funciona.

Te dejo un ejemplo de como lo haría yo. Adáptalo para tu uso, que entiendo que quieres añadirlo a clases por si tienes varios navs y demás. O corrige los errores que te comenté.

Código (javascript) [Seleccionar]
const html = document.querySelector("html");
const body = document.querySelector("body");
const nav = document.createElement("nav");
const otroNav = document.createElement("nav");
const enlace = document.createElement("a");
const otroEnlace = document.createElement("a");

html.style.backgroundColor = "gray";

enlace.innerText = "Mi enlace (hijo de nav)";
enlace.style.display = "block";
enlace.style.border = "3px solid black";
enlace.style.width = "40%";
enlace.style.height = "3em";

otroEnlace.innerText = "Mi otro enlace (también hijo del nav que quiero trackear)";
otroEnlace.style.border = "3px solid black";
otroEnlace.style.position = "fixed";
otroEnlace.style.bottom = "80px";
otroEnlace.style.left = "6px";
otroEnlace.style.fontSize = "1.3em";

nav.style.height = "200px";
nav.style.width = "90%";
nav.style.backgroundColor = "red";
nav.innerText = "Esto es un ejemplo";
nav.id = "navQueQuieroTrackear";

otroNav.style.height = "200px";
otroNav.style.width = "90%";
otroNav.style.backgroundColor = "orange";
otroNav.innerText = "Otro nav";

body.style.width = "100%";
body.style.height = "900px";
body.backgroundColor = "green";

nav.appendChild(enlace);
nav.appendChild(otroEnlace);
body.appendChild(nav);
body.appendChild(otroNav);                                                             

window.addEventListener("click", evt => {
  const tagName = evt.target.outerHTML.substr(1, 15).split(" ")[0]; // obtener etiqueta clickada.
  alert("Clickeaste el elemento " + tagName);

  const nav = document.querySelector("#navQueQuieroTrackear");
  const id = evt.target.id; // obten id del elemento clickado
  if (id === nav.id) { // se clickeo el nav que busco
    alert("Nav clickeado"); // xD
    nav.style.opacity = "1"; // 0 es invisible, 1 es visible.
  } else {
    // comprueba si el elemento clickado es hijo del nav
    let isChildOfNav = false; // auxiliar
    const navChilds = document.querySelectorAll("#navQueQuieroTrackear > *"); // selecciona todos los hijos del nav
    evt.target.currentLoopedElementTemporalId = true; // propiedad que uso de auxiliar para detectar si alguno de los hijos la tiene (A.K.A, es el mismo elemento)
    for (let i in navChilds) { // recorre los hijos
      if (navChilds[i]?.currentLoopedElementTemporalId) { // comprueba si el hijo actual tiene la propiedad
        // el elemento iterado es el mismo que el clickeado (es decir, el elemento clickeado es hijo del nav
        isChildOfNav = true;
        evt.target.currentLoopedElementTemporalId = null; // elimina la propiedad auxiliar
        break; // ya sabemos que es hijo, deja de iterar
      }
    }

    if (isChildOfNav) { // si se clickeo un hijo de nav
      alert("Es un hijo de nav");
      nav.style.opacity = "1";
    } else { // si no es hijo de nav
      alert("No es hijo de nav");
      nav.style.opacity = "0.2"; // haz el nav casi invisible
    }
  }


});

V0LT4GE

Cita de: @XSStringManolo en 16 Noviembre 2021, 05:19 AM
No es buena idea añadir listeners cuando se cumpla una condición. En código donde en distintos momentos se cumpla una u otra, si no eliminas el listemer anterior y simplemente añades uno nuevo, se te van a acumular el listener antiguo y el nuevo....

Te agradezco mucho la aportacion, leere la
documentacion de add event listener que me comentas,
voy a intentar implementarlo de la manera que me comentas, te agradezco muchisimo  :D