Skip to content

Todo para WordPress, el desarrollo web — y mucho más

🔄 JQuery .toggle(): alternancia moderna y reemplazo del método eliminado

🔄 JQuery .toggle(): alternancia moderna y reemplazo del método eliminado

¿Encontró un fragmento de jQuery ya hecho para un botón de «Mostrar/Ocultar» que no funciona? El código que usa .toggle() se escribió siguiendo un manual de hace una década y dejó de funcionar silenciosamente en jQuery 1.9. Para un principiante, esta situación parece magia negra: la consola está vacía, no hay errores, el botón simplemente no responde a un segundo clic.

El problema es que el método .toggle() en jQuery tuvo dos vidas. La primera, animar la visibilidad de elementos, sigue viva. La segunda, alternar acciones al hacer clic, se eliminó en 2013, pero los motores de búsqueda todavía muestran artículos antiguos como primeros resultados. Aquí explicaremos por qué el código antiguo está muerto y escribiremos tres alternativas funcionales, desde una bandera simple hasta atributos de datos para una docena de botones a la vez.

💡 Resumen rápido:

  • Por qué su .toggle(fn1, fn2) no funciona y dónde buscar código obsoleto
  • Método 1: una variable de estado para un solo botón con código mínimo
  • Método 2: .data() cuando tiene muchos botones y cada uno vive su propia vida
  • Extra: tres o más acciones en una cadena de clics usando un contador
  • .toggle() moderno para animación, lo que permanece y cómo usarlo

Qué es.toggle() en jQuery y por qué el código antiguo está muerto

Antes de jQuery 1.8, el método .toggle() podía hacer dos cosas diferentes según los argumentos pasados. Si pasaba dos parámetros de función, funcionaba como un alternador: el primer clic ejecutaba la primera función, el segundo clic ejecutaba la segunda, el tercer clic ejecutaba la primera de nuevo, y así sucesivamente en un ciclo.

Se veía compacto:

1// Worked in jQuery before 1.8, removed in 1.9
2$('#myButton').toggle(
3 function() {
4 $(this).text('Show categories').css('background', 'green');
5 },
6 function() {
7 $(this).text('Hide categories').css('background', 'red');
8 }
9);

Exactamente este código ha estado circulando en blogs en español hasta el día de hoy. El problema es que con el lanzamiento de jQuery 1.9 (enero de 2013), esta forma de .toggle() se eliminó por completo. La razón: el doble propósito del método creaba confusión, y los principiantes no entendían por qué .toggle() a veces animaba y a veces alternaba acciones.

Hoy .toggle() hace solo una cosa: muestra u oculta un elemento con animación. Para acciones alternantes, el desarrollador necesita gestionar el estado explícitamente.

Método 1: variable de estado

El enfoque más directo es crear una variable booleana y alternarla en el manejador .click(). Adecuado para un solo botón o elementos con lógica de alternancia compartida.

Agregue el código a su archivo de scripts del tema (vía wp_enqueue_script en functions.php) o en un bloque <script> antes del cierre de </body>:

1let isFirstClick = true;
2
3$('#toggleBtn').on('click', function() {
4 const $btn = $(this);
5
6 if (isFirstClick) {
7 $btn.text('Hide categories');
8 $('#contentBlock').show(700);
9 isFirstClick = false;
10 } else {
11 $btn.text('Show categories');
12 $('#contentBlock').fadeOut('slow');
13 isFirstClick = true;
14 }
15});

Aquí isFirstClick almacena el estado actual fuera del manejador. El primer clic muestra el bloque y establece la bandera en false, el segundo lo oculta y devuelve la bandera a su estado original. Sin magia: usted sabe exactamente qué acción ocurrirá ahora y cuál ocurrirá después.

La ventaja de este enfoque es que la bandera se puede reiniciar desde cualquier parte del programa. Por ejemplo, después de una solicitud AJAX quiere devolver el botón a su estado inicial, solo use isFirstClick = true.

La desventaja es una variable para todos los botones. Si la página tiene dos alternadores independientes con la clase .toggleBtn, la variable isFirstClick será compartida por ambos. Para tal escenario, use el método 2.

Método 2: atributos de datos de jQuery

Cuando tiene varios botones independientes (por ejemplo, cada producto en un catálogo tiene su propio bloque de especificaciones), necesita almacenar el estado directamente en el elemento DOM. El método .data() adjunta datos arbitrarios a un elemento sin contaminar el ámbito global.

Cargue el script de la misma manera, vía wp_enqueue_script o en el pie de página:

1$('.toggle-btn').on('click', function() {
2 const $btn = $(this);
3 const hasClicked = $btn.data('clicked') || false;
4
5 if (!hasClicked) {
6 $btn.text('Hide specifications').css('background', '#f0f0f0');
7 $btn.next('.specs-block').show(400);
8 $btn.data('clicked', true);
9 } else {
10 $btn.text('Show specifications').css('background', '#fff');
11 $btn.next('.specs-block').fadeOut(300);
12 $btn.data('clicked', false);
13 }
14});

Llamar a $btn.data('clicked') lee el estado de este botón específico. Diez botones en la página significan diez estados aislados. Sin conflictos.

Nota: .data() trabaja con la memoria de jQuery, no con atributos HTML data-*. Si necesita que el estado sobreviva a una recarga de página, adicionalmente escriba $btn.attr('data-clicked', 'true') y lea vía .attr().

Extra: tres o más acciones en una cadena

¿Qué pasa si no debe haber dos sino tres clics? Por ejemplo: la primera pulsación muestra el bloque, la segunda cambia su contenido, la tercera lo oculta. Aquí, en lugar de una bandera booleana, crea un contador numérico:

1$('#multiBtn').on('click', function() {
2 const $btn = $(this);
3 let count = $btn.data('clickCount') || 0;
4
5 switch (count) {
6 case 0:
7 $btn.text('Step 1: show block');
8 $('#targetBlock').show(500);
9 break;
10 case 1:
11 $btn.text('Step 2: load data');
12 $('#targetBlock').load('/ajax-content');
13 break;
14 case 2:
15 $btn.text('Step 3: hide');
16 $('#targetBlock').fadeOut(400);
17 count = -1; // next click will become case 0 again
18 break;
19 }
20
21 $btn.data('clickCount', count + 1);
22});

Reiniciar el contador (count = -1) tiene sentido si la cadena debe repetirse. Si la acción es única, simplemente elimine el reinicio, y no ocurrirá nada después del tercer clic.

.Toggle() moderno para animación

La forma de .toggle() que sobrevivió es estrictamente responsable de la visibilidad del elemento. Sin argumentos, es una alternancia instantánea. Con duración, anima ancho, alto y opacidad simultáneamente.

Escenario básico: un botón «Mostrar/Ocultar menú»:

1$('#menuToggle').on('click', function() {
2 $('#mainMenu').toggle('slow', function() {
3 // callback after animation completes
4 console.log('Animation complete');
5 });
6});

Las cadenas 'fast' y 'slow' dan 200 y 600 milisegundos respectivamente. Puede pasar un número exacto: .toggle(400) significa 400 ms.

Un truco útil: forzar el estado mediante un parámetro booleano. .toggle(true) siempre muestra el elemento, y .toggle(false) siempre lo oculta. Esto es conveniente en combinación con una bandera externa del método 1:

1let visible = true;
2$('#toggleBtn').on('click', function() {
3 visible = !visible;
4 $('#content').toggle(visible);
5});

El código se lee linealmente: la bandera se invierte, el elemento toma el estado requerido. Sin if/else condicional alrededor de la visibilidad.

⁉️🤔 Preguntas frecuentes

¿Por qué mi código antiguo con .toggle(fn1, fn2) no muestra errores en la consola?

La forma antigua de .toggle() se eliminó a nivel de método: jQuery simplemente no encuentra tal firma y no hace nada silenciosamente. La consola está vacía porque llamar a .toggle(fn1, fn2) para jQuery moderno es una llamada sintácticamente correcta pero sin sentido (los argumentos se ignoran). Verifique su versión de jQuery: si es 1.9 o superior, el código antiguo está muerto.

¿Puedo incluir jQuery Migrate y no reescribir el código?

Técnicamente, sí. El plugin jQuery Migrate restaura métodos eliminados, incluido el antiguo .toggle(). Pero esto es un parche temporal: Migrate añade ~10 KB minificados y está diseñado para un período de transición, no para uso permanente. Si el sitio funciona con WordPress y jQuery se carga desde el núcleo, Migrate ya está allí por compatibilidad hacia atrás. Pero no se recomienda confiar en él en su propio código: puede desactivarse en cualquier momento por una actualización del tema o plugin.

¿Qué es mejor, una variable o un atributo de datos?

Para un solo botón, use una variable (menos código). Para varios botones independientes o elementos añadidos dinámicamente, use .data() (aislamiento de estado). Si los botones se añaden vía AJAX después de cargar la página, use delegación: $(document).on('click', '.toggle-btn', function() { ... }).

¿Funciona.toggle() en dispositivos móviles?

Sí. El .toggle() moderno (animación) y todos los manejadores de clic de este artículo funcionan correctamente en eventos táctiles. jQuery normaliza click para navegadores móviles desde sus primeras versiones. El único matiz: en iOS antes de la versión 12, los elementos sin cursor: pointer tenían un clic retardado, pero este problema se resuelve con una línea CSS touch-action: manipulation para el botón.

¿Dónde debo colocar el código jQuery en WordPress?

Tres opciones. Rápida: el plugin Code Snippets: inserte código JS en un fragmento con tipo «JavaScript», y se carga automáticamente en el pie de página. Correcta: cree un archivo js/toggle.js en su tema hijo, regístrelo vía wp_enqueue_script('my-toggle', get_stylesheet_directory_uri() . '/js/toggle.js', array('jquery'), '1.0', true) en functions.php. El parámetro true al final envía el script al pie de página, lo cual es estándar para código que trabaja con el DOM. No ponga <script> directamente en el cuerpo de la entrada; el editor de WordPress eliminará la etiqueta.

Qué enfoque elegir para su proyecto

Si tiene un botón con alternancia de texto y visibilidad de bloque, use una variable de estado. Tres líneas, comportamiento transparente, depuración trivial.

Si hay múltiples alternadores (catálogo, panel de configuración, lista de elementos expandibles), use solo .data(). Una variable global para múltiples botones creará una condición de carrera de estado que depurará más tiempo del que toma escribir el código usando el método 2.

Una cadena de tres o más pasos requiere un contador con switch. No complique con banderas booleanas lo que naturalmente encaja con números.

Lo más importante, si encuentra un artículo en los resultados de búsqueda con .toggle(fn1, fn2), cierre la pestaña. jQuery está vivo, pero ese método específico fue enterrado en 2013.

Puede refrescar sus conocimientos sobre la ejecución de fragmentos de JavaScript al vuelo en nuestro artículo sobre trabajar con fragmentos en Chrome DevTools, lo cual será útil para probar rápidamente el código de este artículo.