Foros del Web » Programando para Internet » Javascript »

[SOLUCIONADO] Intentando cambiar "foreach" por "for"

Estas en el tema de Intentando cambiar "foreach" por "for" en el foro de Javascript en Foros del Web. Hola a todos. Tengo esta función que hace su trabajo de forma parcial por problemas de compatibilidad de foreach en diversos navegadores. Código: var toggles ...
  #1 (permalink)  
Antiguo 07/11/2019, 05:30
 
Fecha de Ingreso: noviembre-2005
Mensajes: 883
Antigüedad: 14 años
Puntos: 8
Intentando cambiar "foreach" por "for"

Hola a todos.

Tengo esta función que hace su trabajo de forma parcial por problemas de compatibilidad de foreach en diversos navegadores.

Código:
var toggles = document.querySelectorAll('.selector');
var active = null;
function toggleSubmenus (event) {
  var current = event.target;
  var isCurrentActive = current === active;

  toggles.forEach(function (toggle) {
    toggle.classList.toggle('visible', toggle === current && !isCurrentActive);
  });
  active = isCurrentActive ? null : current;
}
toggles.forEach(function(toggle) {
  toggle.addEventListener('click', toggleSubmenus);
});
Quiero cambiar foreach por for. Parece que hay diversas alternativas pero ninguna me ha funcionado. Quiero hacerlo sin jQuery. Supongo que será posible pero hasta ahora no me resulta nada.

He intentado hacerlo así (uno de los intentos):

Código:
var toggles = document.querySelectorAll('.selector');
var active = null;
function toggleSubmenus (event) {
  var current = event.target;
  var isCurrentActive = current === active;

for (let i = 0; i < toggles.length; i++) {
function (toggle) {
    toggle.classList.toggle('visible', toggle === current && !isCurrentActive);
  }
};
  active = isCurrentActive ? null : current;
}
for (let i = 0; i < toggles.length; i++) {
function(toggle) {
  toggle.addEventListener('click', toggleSubmenus);
}
};
Sin resultado.

¿Me podéis echar un cable???

Última edición por JUMASOL; 07/11/2019 a las 05:39
  #2 (permalink)  
Antiguo 07/11/2019, 05:47
 
Fecha de Ingreso: abril-2011
Mensajes: 42
Antigüedad: 8 años, 7 meses
Puntos: 10
Respuesta: Intentando cambiar "foreach" por "for"

Resulta que el método forEach de la clase NodeList no está soportado por Internet Explorer. Supongo que por eso quieres utilizar un bucle for en vez de forEach.

Tienes dos opciones, usar el bucle for que comentas:

Código Javascript:
Ver original
  1. var toggles = document.querySelectorAll('.selector');
  2. var active = null;
  3. function toggleSubmenus (event) {
  4.   var current = event.target;
  5.   var isCurrentActive = current === active;
  6.  
  7.   for(var i = 0; i < toggles.length; i++){
  8.       toggles[i].classList.toggle('visible', toggles[i] === current && !isCurrentActive);
  9.   }
  10.   active = isCurrentActive ? null : current;
  11. }
  12. for(var i = 0; i < toggles.length; i++){
  13.     toggles[i].addEventListener('click', toggleSubmenus);
  14. }

O una opción más elegante, usar un polyfill (y así no necesitas cambiar el código cada vez que aparezca forEach):

Código Javascript:
Ver original
  1. // Polyfill:
  2.  
  3. if (window.NodeList && !NodeList.prototype.forEach) {
  4.     NodeList.prototype.forEach = Array.prototype.forEach;
  5. }
  6.  
  7. // Debajo pones el resto de tu codigo en el que usas forEach:
  8.  
  9. var toggles = document.querySelectorAll('.selector');
  10. var active = null;
  11. function toggleSubmenus (event) {
  12.   var current = event.target;
  13.   var isCurrentActive = current === active;
  14.  
  15.   toggles.forEach(function (toggle) {
  16.     toggle.classList.toggle('visible', toggle === current && !isCurrentActive);
  17.   });
  18.   active = isCurrentActive ? null : current;
  19. }
  20. toggles.forEach(function(toggle) {
  21.   toggle.addEventListener('click', toggleSubmenus);
  22. });


  #3 (permalink)  
Antiguo 07/11/2019, 06:10
 
Fecha de Ingreso: noviembre-2005
Mensajes: 883
Antigüedad: 14 años
Puntos: 8
Respuesta: Intentando cambiar "foreach" por "for"

Gracias prueba230683, ambos funcionan pero añaden un problema en Internet Explorer, y puede que en algún otro.

El script es para hace un toggle de clases en dos enlaces. Sin actuar sobre la página, ambos carecen de clase (que sería "active"). Si pulsas uno, se inserta la clase para un efecto con css. Si lo vuelves a pulsar desaparece. Y lo mismo si pulsas el otro enlace, que activa su clase y desactiva la del otro.

Se trata de dos listas descendentes ocultas que deben mostrarse cuando el enlace sobre las mismas tiene el active. Cuando una está activa, la otra no por razones obvias.

Funciona en Chrome, Firefox y otros. Pero en IE lo que pasa cuando pulsas cualquiera de los dos enlaces es que se muestran las dos listas, si pulsas luego cualquiera de ellos, sea el que has pulsado o el otro, desaparecen las dos listas.

Estoy por dejarlo así, pero si se puede arreglar mejor.
  #4 (permalink)  
Antiguo 07/11/2019, 06:20
 
Fecha de Ingreso: abril-2011
Mensajes: 42
Antigüedad: 8 años, 7 meses
Puntos: 10
Respuesta: Intentando cambiar "foreach" por "for"

Dos preguntas,

¿De qué versión de IE estamos hablando? Porque hay versiones muy antiguas (antes de la 9, creo) que en vez de event.target usan event.srcElement.

¿Te muestra algún error en la consola?
  #5 (permalink)  
Antiguo 07/11/2019, 06:32
 
Fecha de Ingreso: noviembre-2005
Mensajes: 883
Antigüedad: 14 años
Puntos: 8
Respuesta: Intentando cambiar "foreach" por "for"

Es IE11 y no muestra nada en consola.
  #6 (permalink)  
Antiguo 07/11/2019, 07:25
 
Fecha de Ingreso: abril-2011
Mensajes: 42
Antigüedad: 8 años, 7 meses
Puntos: 10
Respuesta: Intentando cambiar "foreach" por "for"

Si miras la tabla de compatibilidad del método toggle:

https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle#Browser_compatibility

Verás que IE11 no soporta el segundo parámetro de dicho método, por eso no funciona bien.
La solución es simular la funcionalidad de este parámetro, es decir, si la expresión toggle === current && !isCurrentActive es true, se añade la clase con .add, y si es false, se elimina la clase con .remove:

Código Javascript:
Ver original
  1. // Polyfill:
  2.  
  3. if (window.NodeList && !NodeList.prototype.forEach) {
  4.     NodeList.prototype.forEach = Array.prototype.forEach;
  5. }
  6.  
  7. // Debajo pones el resto de tu codigo en el que usas forEach:
  8.  
  9. var toggles = document.querySelectorAll('.selector');
  10. var active = null;
  11. function toggleSubmenus (event) {
  12.   var current = event.target;
  13.   var isCurrentActive = current === active;
  14.  
  15.   toggles.forEach(function (toggle) {
  16.     if(toggle === current && !isCurrentActive){
  17.       toggle.classList.add('visible');
  18.     }else{
  19.       toggle.classList.remove('visible');
  20.     }
  21.   });
  22.   active = isCurrentActive ? null : current;
  23. }
  24. toggles.forEach(function(toggle) {
  25.   toggle.addEventListener('click', toggleSubmenus);
  26. });

De esta forma consigues el mismo efecto, pero ahora debería funcionar en IE11.


Ojalá algún día deje de existir IE
  #7 (permalink)  
Antiguo 07/11/2019, 07:55
 
Fecha de Ingreso: noviembre-2005
Mensajes: 883
Antigüedad: 14 años
Puntos: 8
Respuesta: Intentando cambiar "foreach" por "for"

Ahora sí que funciona.

Eres un maestro prueba230683.

Y lo que dices de IE, llegará antes de lo que creemos.

Yo soy un dummy en js y programación en general, pero experto en diseño, y si tú llevas tiempo en este mundo recordarás los días que pasamos adaptando webs a IE5 y 6, entre otras cosas que hoy están más que olvidadas, y eso que no fue hace tanto.

Gracias por tu ayuda.



La zona horaria es GMT -6. Ahora son las 15:16.