
🔄 jQuery .toggle(): современный переключатель и замена удалённого метода
Нашли готовый jQuery-сниппет для кнопки «Показать/Скрыть», а он не работает? Код с .toggle() писался по мануалу десятилетней давности и молча сломался ещё в jQuery 1.9. Для новичка такая ситуация выглядит как чёрная магия: консоль пустая, ошибок нет, кнопка просто не реагирует на повторный клик.
Проблема в том, что у метода .toggle() в jQuery было две жизни. Первая, анимация показа/скрытия элементов: жива до сих пор. Вторая, чередование действий по клику: её удалили в 2013 году, но поисковики до сих пор выдают старые статьи как основные. Здесь мы разберём, почему старый код мёртв, и напишем три работающие альтернативы, от простого флага до data-атрибутов для десятка кнопок сразу.
💡 Быстрый обзор:
- Почему ваш
.toggle(fn1, fn2)не работает и где искать устаревший код - Способ 1: переменная состояния, для одиночной кнопки, минимум кода
- Способ 2:
.data(), когда кнопок много и каждая живёт своей жизнью - Бонус: три и более действий на цепочке кликов через счётчик
- Современный
.toggle()для анимации, что осталось и как использовать
Что такое.toggle() в jQuery и почему старый код мёртв
До jQuery 1.8 метод .toggle() умел две разные вещи в зависимости от переданных аргументов. Если передать два параметра-функции, он работал как переключатель: первый клик запускал первую функцию, второй клик, вторую, третий, снова первую, и так по кругу.
Выглядело это компактно:
1 // Работало в jQuery до 1.8, удалено в 1.9 2 $('#myButton').toggle( 3 function() { 4 $(this).text('Показать категории').css('background', 'green'); 5 }, 6 function() { 7 $(this).text('Скрыть категории').css('background', 'red'); 8 } 9 );
Ровно такой код кочует по русскоязычным блогам до сих пор. Проблема в том, что с выходом jQuery 1.9 (январь 2013 года) эту форму .toggle() убрали полностью. Причина, двойное назначение метода создавало путаницу: новички не понимали, почему .toggle() то анимирует, то переключает действия.
Сегодня .toggle() делает только одно, показывает или скрывает элемент с анимацией. А для чередования действий разработчику нужно явно управлять состоянием.
Способ 1: переменная состояния
Самый прямой путь, завести булеву переменную и переключать её в обработчике .click(). Подходит для одиночной кнопки или элементов, у которых логика переключения общая.
Добавьте код в файл скриптов темы (через wp_enqueue_script в functions.php) или в блок <script> перед закрывающим </body>:
1 let isFirstClick = true; 2 3 $('#toggleBtn').on('click', function() { 4 const $btn = $(this); 5 6 if (isFirstClick) { 7 $btn.text('Скрыть категории'); 8 $('#contentBlock').show(700); 9 isFirstClick = false; 10 } else { 11 $btn.text('Показать категории'); 12 $('#contentBlock').fadeOut('slow'); 13 isFirstClick = true; 14 } 15 });
Здесь isFirstClick хранит текущее состояние снаружи обработчика. Первый клик показывает блок и меняет флаг на false, второй, скрывает и возвращает флаг обратно. Никакой магии: вы точно знаете, какое действие произойдёт сейчас и какое, следующим.
Плюс подхода в том, что флаг можно сбросить из любого места программы. Скажем, после AJAX-запроса вы хотите вернуть кнопку в исходное положение, просто isFirstClick = true.
Минус, одна переменная на все кнопки. Если на странице два независимых переключателя с классом .toggleBtn, переменная isFirstClick будет общей для обоих. Для такого сценария, способ 2.
Способ 2: data-атрибуты jQuery
Когда у вас несколько независимых кнопок (например, у каждого товара в каталоге свой блок с характеристиками), состояние нужно хранить прямо на DOM-элементе. Метод .data() привязывает произвольные данные к элементу и не загрязняет глобальную область видимости.
Загрузите скрипт тем же способом, через wp_enqueue_script или в футере:
1 $('.toggle-btn').on('click', function() { 2 const $btn = $(this); 3 const hasClicked = $btn.data('clicked') || false; 4 5 if (!hasClicked) { 6 $btn.text('Скрыть характеристики').css('background', '#f0f0f0'); 7 $btn.next('.specs-block').show(400); 8 $btn.data('clicked', true); 9 } else { 10 $btn.text('Показать характеристики').css('background', '#fff'); 11 $btn.next('.specs-block').fadeOut(300); 12 $btn.data('clicked', false); 13 } 14 });
Вызов $btn.data('clicked') читает состояние конкретно этой кнопки. Десять кнопок на странице, десять изолированных состояний. Никаких конфликтов.
Обратите внимание: .data() работает с памятью jQuery, а не с HTML-атрибутами data-*. Если вам нужно, чтобы состояние пережило перезагрузку страницы, дополнительно пишите $btn.attr('data-clicked', 'true') и читайте через .attr().
Бонус: три и более действий по цепочке
Что если кликов должно быть не два, а три? Скажем: первое нажатие, показать блок, второе, изменить его содержимое, третье, скрыть. Здесь вместо булева флага заводят числовой счётчик:
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('Шаг 1: показать блок'); 8 $('#targetBlock').show(500); 9 break; 10 case 1: 11 $btn.text('Шаг 2: загрузить данные'); 12 $('#targetBlock').load('/ajax-content'); 13 break; 14 case 2: 15 $btn.text('Шаг 3: скрыть'); 16 $('#targetBlock').fadeOut(400); 17 count = -1; // следующий клик снова станет case 0 18 break; 19 } 20 21 $btn.data('clickCount', count + 1); 22 });
Сбрасывать счётчик (count = -1) имеет смысл, если цепочка должна зацикливаться. Если действие разовое, просто уберите сброс, и после третьего клика ничего происходить не будет.
Современный.toggle() для анимации
Та форма .toggle(), которая выжила, отвечает строго за видимость элементов. Без аргументов, мгновенное переключение. С duration, анимация ширины, высоты и прозрачности одновременно.
Базовый сценарий: кнопка «Показать/Скрыть меню»:
1 $('#menuToggle').on('click', function() { 2 $('#mainMenu').toggle('slow', function() { 3 // колбэк после завершения анимации 4 console.log('Анимация завершена'); 5 }); 6 });
Строки 'fast' и 'slow' дают 200 и 600 миллисекунд соответственно. Можно передать точное число: .toggle(400), 400 мс.
Полезный приём: принудительное состояние через булев параметр. .toggle(true) всегда показывает элемент, а .toggle(false) всегда скрывает. Это удобно в связке с внешним флагом из способа 1:
1 let visible = true; 2 $('#toggleBtn').on('click', function() { 3 visible = !visible; 4 $('#content').toggle(visible); 5 });
Код читается линейно: флаг перевернули, элемент принял нужное состояние. Никаких условных if/else вокруг видимости.
⁉️🤔 Частые вопросы
Почему мой старый код с .toggle(fn1, fn2) не выдаёт ошибок в консоли?
Старая форма
.toggle()удалена на уровне метода: jQuery просто не находит такую сигнатуру и молча ничего не делает. Консоль пустая, потому что вызов.toggle(fn1, fn2)для современного jQuery, это синтаксически корректный, но бессмысленный вызов (аргументы игнорируются). Проверьте версию jQuery: если 1.9 или выше, старый код мёртв.
Можно ли подключить jQuery Migrate и не переписывать код?
Формально, да. Плагин jQuery Migrate восстанавливает удалённые методы, включая старый
.toggle(). Но это временный костыль: Migrate добавляет ~10 КБ в сжатом виде и рассчитан на период перехода, а не на постоянную работу. Если сайт на WordPress и jQuery грузится из ядра, Migrate там уже есть для обратной совместимости. Но полагаться на него в собственном коде не стоит: в любой момент он может быть отключён обновлением темы или другого плагина.
Что лучше, переменная или data-атрибут?
Для одной кнопки, переменная (меньше кода). Для нескольких независимых кнопок или динамически добавляемых элементов,
.data()(изоляция состояний). Если кнопки добавляются через AJAX после загрузки страницы, используйте делегирование:$(document).on('click', '.toggle-btn', function() { ... }).
Работает ли.toggle() на мобильных устройствах?
Да. Современный
.toggle()(анимация) и все обработчики клика из этой статьи корректно отрабатывают на тач-событиях. jQuery нормализуетclickдля мобильных браузеров начиная с первых версий. Единственный нюанс: на iOS до 12-й версии у элементов безcursor: pointerбыл задержанный клик, но эта проблема решается одной CSS-строкойtouch-action: manipulationдля кнопки.
Где размещать jQuery-код в WordPress?
Три варианта. Быстрый, плагин Code Snippets: вставляете JS-код в сниппет с типом «JavaScript», он автоматически подгружается в футере. Правильный, создать в дочерней теме файл
js/toggle.js, зарегистрировать его черезwp_enqueue_script('my-toggle', get_stylesheet_directory_uri() . '/js/toggle.js', array('jquery'), '1.0', true)вfunctions.php. Параметрtrueв конце отправляет скрипт в футер, это стандарт для кода, работающего с DOM. Не ставьте<script>прямо в тело поста, редактор WordPress обрежет тег.
Какой подход выбрать для вашего проекта
Если у вас одна кнопка с переключением текста и видимости блока, берите переменную состояния. Три строки, поведение прозрачное, отладка тривиальная.
Если переключателей несколько (каталог, панель настроек, список элементов с раскрытием), только .data(). Глобальная переменная на несколько кнопок породит гонку состояний, которую вы будете отлаживать дольше, чем написать код по способу 2.
Цепочка из трёх и более шагов, счётчик со switch. Не усложняйте булевыми флагами то, что естественно ложится на числа.
А главное, если встретили в поиске статью с .toggle(fn1, fn2), закройте вкладку. jQuery жив, но тот конкретный метод похоронен в 2013 году.
Освежить знания по запуску JavaScript-фрагментов на лету можно в нашем материале о работе со сниппетами в Chrome DevTools, пригодится для быстрой обкатки кода из этой статьи.



