¿Cómo arreglar un bug en mi barra de búsqueda con dropdown?

  • Autor Autor Angelicahg
  • Fecha de inicio Fecha de inicio
Angelicahg

Angelicahg

Gamma
Verificado
Verificación en dos pasos activada
Verificado por Whatsapp
Verificado por Binance
Hola, estoy intentando hacer una barra de busquedad con dropdown, lo logre pero tengo que un bug que no logro solucionar y seguro es una tonteria D:


1747512549031.webp
1747512563564.webp


En las dos primeras imagenes se puede ver como funciona bien mi dropdown pero el problema viene si doy clic afuera de los botones por ejemplo donde marque en verde en esta tercera imagen.

1747512633372.webp


Si hago clic allí y luego intento ir al boton de busquedad el input del texto me sale como bloqueado asi no me deja teclear alli.

1747512672616.webp


Mmm, ya no se que hacer.

Este es mi JS


JavaScript:
// ✅ filtros_usuarios.js - búsqueda, orden, tipo y reset con fix real y completo

document.addEventListener('DOMContentLoaded', () => {
  const inputBuscar = document.getElementById('buscarUsuario');
  const contenedor = document.getElementById('contenedor-usuarios');

  if (inputBuscar && contenedor) {
    inputBuscar.addEventListener('input', () => {
      const valor = inputBuscar.value.toLowerCase();
      const tarjetas = contenedor.querySelectorAll('.tarjeta-usuario:not(.fila-seleccionar-todos):not(.tarjeta-vacia)');
      tarjetas.forEach(tarjeta => {
        const nombre = tarjeta.querySelector('h3')?.textContent.toLowerCase() || '';
        tarjeta.style.display = nombre.includes(valor) ? 'flex' : 'none';
      });

      const visibles = Array.from(tarjetas).filter(t => t.style.display !== 'none').length;
      const spanContador = document.getElementById('cantidad-usuarios');
      if (spanContador) spanContador.textContent = visibles;
    });
  }

  // ===============================
  // Orden A-Z / Z-A
  // ===============================
  document.querySelectorAll('[data-orden]').forEach(opcion => {
    opcion.addEventListener('click', (e) => {
      e.stopPropagation();
      const orden = opcion.dataset.orden;
      const tarjetas = Array.from(document.querySelectorAll('.tarjeta-usuario'))
        .filter(t => !t.classList.contains('fila-seleccionar-todos') && !t.classList.contains('tarjeta-vacia'));

      tarjetas.sort((a, b) => {
        const aTexto = a.querySelector('h3')?.textContent.toLowerCase() || '';
        const bTexto = b.querySelector('h3')?.textContent.toLowerCase() || '';
        return orden === 'az' ? aTexto.localeCompare(bTexto) : bTexto.localeCompare(aTexto);
      });

      const lista = document.getElementById('contenedor-usuarios');
      tarjetas.forEach(t => lista.appendChild(t));
    });
  });

  // ===============================
  // Filtro por tipo
  // ===============================
  document.querySelectorAll('[data-tipo]').forEach(opcion => {
    opcion.addEventListener('click', (e) => {
      e.stopPropagation();
      const tipo = opcion.dataset.tipo;
      if (typeof cargarUsuarios === 'function') cargarUsuarios(tipo);
      document.querySelectorAll('[data-tipo]').forEach(opt => opt.classList.remove('activo'));
      opcion.classList.add('activo');
    });
  });

  // ===============================
  // Dropdowns con autofocus corregido
  // ===============================
  document.querySelectorAll('.filtro-btn').forEach(boton => {
    boton.addEventListener('click', function (e) {
      e.stopPropagation();
      const dropdown = this.closest('.filtro-dropdown');

      // Cerrar otros dropdowns
      document.querySelectorAll('.filtro-dropdown').forEach(d => {
        if (d !== dropdown) d.classList.remove('activo');
      });

      // Toggle actual
      dropdown.classList.toggle('activo');

      // Forzar focus si es búsqueda
      if (dropdown.id === 'dropdown-busqueda' && dropdown.classList.contains('activo')) {
        const input = dropdown.querySelector('input');
        if (input) {
          setTimeout(() => {
            input.focus();
            input.select();
            console.log("✅ Autofocus aplicado con delay");
          }, 50);
        }
      }
    });
  });

  // ===============================
  // Cerrar dropdowns al hacer clic fuera (menos si haces clic en el input)
  // ===============================
  document.addEventListener('click', (e) => {
    const abierto = document.querySelector('.filtro-dropdown.activo');
    const esInput = e.target.id === 'buscarUsuario';
    const esDentroDropdown = e.target.closest('.filtro-dropdown');

    if (!esDentroDropdown && !esInput && abierto) {
      abierto.classList.remove('activo');
    }
  });

  // ===============================
  // Prevenir cierre al hacer clic dentro del popup
  // ===============================
  document.querySelectorAll('.popup-filtro').forEach(popup => {
    popup.addEventListener('click', (e) => e.stopPropagation());
  });

  // ===============================
  // Reset filtros
  // ===============================
  const btnReset = document.getElementById('resetFiltros');
  if (btnReset) {
    btnReset.addEventListener('click', () => {
      const inputBuscar = document.getElementById('buscarUsuario');
      if (inputBuscar) {
        inputBuscar.value = '';
        inputBuscar.dispatchEvent(new Event('input'));
      }

      document.querySelectorAll('[data-tipo]').forEach(opt => opt.classList.remove('activo'));
      const defaultTipo = document.querySelector('[data-tipo="activos"]') || document.querySelector('[data-tipo="todos"]');
      if (defaultTipo) defaultTipo.classList.add('activo');

      if (typeof cargarUsuarios === 'function') {
        cargarUsuarios(defaultTipo?.dataset.tipo || 'activos');
      }
    });
  }
});


Este seria mi CSS


CSS:
.barra-filtros {
  position: relative;
  z-index: 1;
  overflow: visible !important;
}

.filtro-dropdown {
  position: relative;
  display: inline-block;
}

.popup-filtro {
  display: none;
  position: absolute;
  top: 110%;
  left: 0;
  background-color: var(--color-blanco-puro);
  border: 1px solid var(--color-input-border);
  border-radius: var(--radio-bordes);
  padding: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  min-width: 130px;
  z-index: 9999;
}

.popup-filtro.popup-busqueda {
  min-width: 180px;
}

/* ✅ Este es el fix real */
.filtro-dropdown.activo .popup-filtro {
  display: block !important;
}


Si alguien me puede orientar se lo agradeceria
 
Solo te falta lo más importante, ... el código html, con puro css y js no veo nada.
 
El otro problema es como "lee" la lista de usuarios, en la class .tarjeta-usuario dentro del id #contenedor-usuarios,
si de una api o html o js/lista, etc,
te falto eso también
...
y pues hasta ahorita el problema es tu código html , ya que el js funciona ,
y el css, pues, así como esta se lo puse...
 
El otro problema es como "lee" la lista de usuarios, en la class .tarjeta-usuario dentro del id #contenedor-usuarios,
si de una api o html o js/lista, etc,
te falto eso también
...
y pues hasta ahorita el problema es tu código html , ya que el js funciona ,
y el css, pues, así como esta se lo puse...

Ufff gracias, mi código HTML estaba bien. ¡La verdad no sé que era que hacía el fallo que comentaba, pero ya lo solucione, agarre de guía tu código e hice el codigo JS desde 0 y ya me funciona bien todo graciasss, creo que el problema es que aveces junto muchas funciones de JS en un solo codigo recomiendas hacer un documento por cada funcion o esta bien dejarlo asi todo en 1?, y otra vez mil gracias !!
 
es que aveces junto muchas funciones de JS en un solo codigo recomiendas hacer un documento por cada funcion o esta bien dejarlo asi todo en 1?, y otra vez mil gracias !!
puedes poner varias funciones en un mismo archivo.js
el problema seria ponerle nombres normales o repetidos a las funciones y constantes
por ejemplo

si en todos tus códigos sueles poner

datos = extraer(userId)
y
def extraer(userId):
...
return datos

y luego en otro código le puedes cambiar los nombres:

datos_lista o datos_uno, etc
y a la función
def extraer_lista(): def datos_uno(): , etc
 
Atrás
Arriba