Як правильно реалізувати універсальні функції show і hide для DOM елемента? Є кілька поширених варіантів, з різними граблями, які ми розглянемо, і виберемо оптимальний.
Розглянемо найпростішу функцію toggle:
Недоліки такого підходу легко бачити. Наприклад, посилання мають за замовчуванням display: inline. А цей код поставить display = "block".
Для перевірки - клікніть на будь-якому місці цього жовтого div. при цьому зголоситься toggle посилання. І потім - клікніть ще раз для повторного toggle.
Як видно, ховає воно нормально, а ось показ - некоректний.
Аналогічна проблема буде з елементами таблиці, у яких за стандартом display: table-cell.
Цієї проблеми позбавлений наступний варіант:
Замість block властивість display скидається - при цьому елемент отримує display з CSS за замовчуванням, тобто те, яке було спочатку:
Як бачите, все працює вірно.
Але при цьому виникає інша проблема. Властивість display у елемента може відрізнятися від успадкованого з CSS, наприклад:
При цьому обнулення display скине це особливого значення.
Для кращої застосовності розіб'ємо toggle на дві частини: show і hide і налагодимо їх окремо.
Щоб обійти описану вище проблему з перезапису display - при приховуванні елементу будемо записувати старе значення display в атрибут el.displayOld. а при показі - відновлювати.
Тепер show / hide для посилання зі своїм display буде працювати коректно.
Однак, і цей варіант - для нас не більше ніж проміжний.
Функція hide працює відмінно. Про show такого не скажеш.
- По-перше, виклик show до hide скине display. Це поведінка - некоректна, його потрібно поправити.
- По-друге, що більш важливо, якщо елемент захований CSS-класом, то show його не здасться.
Наприклад, show буде непереливки посилання з цього прикладу:
Щоб вирішити ці проблеми, функція show повинна знати, чи показується елемент реально чи ні. Це нам допоможе зробити доступ до Computed Style - обчисленому стилю елемента, доступ до якого робиться по-різному, в залежності від браузера.
Наступна функція бере реальне значення display з Computed Style, тобто таке. яке виходить в результаті застосування всіх CSS-класів і властивостей.
Якщо елемент не показується з-за CSS-класу, то getRealDisplay поверне для нього 'none'.
Ви можете захотіти прибрати цю строчку в цілях оптимізації, щоб зробити show швидше.
Але при цьому show стане функціонувати належним чином при виклику без попереднього hide на елементі з нестандартним display.Де взяти значення display для показу спочатку прихованого елемента? Це зовсім не обов'язково block. тому елемент міг бути посиланням, осередком таблиці, та й взагалі - "правильний" display для показу елемента залежить від місця, часу і настрою програміста.
У блоці (3.2) функція поміщає елемент з таким же тегом в кінець
і отримує його display. яке кешує у допоміжному об'єкті displayCache. Звичайно, це всього лише гіпотеза, однак в простих випадках вона працює.Цей display і використовується для призначення елементу.
- Спробувати отримати правильне значення display з кешу.
- У кеші немає - додаємо порожній тег до . потім беремо його display.
- Якщо і цей тег має реальний display: none - вгадати не вийшло. Візьмемо block. що ще робити, елемент-то показати треба.
- Вгадані значення display застосовуємо до елементу і зберігаємо для подальшого використання.
Отже, тепер на основі show і hide можна зробити функцію toggle. яка видимий елемент приховує, а невидимий - навпаки, показує. Інакше кажучи, перемикає стан елемента.
Функція toggle сама по собі дуже проста:
Для її роботи необхідна допоміжна функція isHidden. яка визначає, чи видно елемент. Само собою, мається на увазі реальна видимість, а не властивість display елемента.
Використовуємо для цього трюк з offsetWidth / offsetHeight:
Ця реалізація намагається отримати відповідь, по можливості використовуючи перевірку offsetWidth / offsetHeight. тому це швидше, ніж getRealDisplay.
Отже, ось підсумковий код toggle.js.
Приклад роботи ви можете побачити на окремій сторінці.
Ця універсальна функція toggle широко використовується в різних бібліотеках, зокрема, в jQuery.
Тепер ви знаєте, що вона робить ряд зайвих операцій, і якщо раптом ваш toggle заглючить - уявляєте, в чому може бути справа.
Нехай ваш toggle завжди працює так, як задумано!
- Версія для друку