Часть 1. Теория
Сейчас использование модальных и не только диалогов на веб-сайтах является вполне нормальным явлением, в следствии чего нам доступна масса уже готовых контролов как для asp.net/…. (подставьте сюда ту технологию, которую вы используете в своих проектах), так и множество плагинов для популярных javascript-фреймворком, таких как jquery, moo tools, prototype и других. Для упрощения договоримся, что здесь под контролом я буду иметь в виду все что, что в итоге превращается в html-код и выглядит как привычное нам модальное диалоговое окно.Реализация диалогового окна на html выглядит следующим образом:
- в какой-то элемент (например, ) помещается весь контент диалогового окна и ставится ему свойства display:none; z-index:100; position:absolute;
- создается “фоновый” элемент для создания эффекта модальности с такими свойствами: background-color:gray; position: absolute; width: 100%; height: 100%; z-index: 90; display:block; opacity:.32; top:0; left:0;display:none; (например, ). - этот пункт нужен только для создания модального диалога;
- при отображении диалогового окна мы меняем у нашего контейнера и фона свойства display на значение block и видим эффект (модального) диалогового окна.
Пример простого pop-up’а находится в файле simple-popup.htmlВсе модальные окна, реализованные на HTML, которые встречал работали по описанному алгоритму. Изменения были лишь в удобстве работы с ними и набором дополнительных фич, таких как: drag-n-drop, поддержка тем, обработчики событий и др.Я всегда использовал этот алгоритм до того момента, как мне не пришлось делать возможность навигации по кнопкам внутри модального диалога с помощью клавиатуры. Для примера, рассмотрим работу диалого, реализованного в файле simple-popup-with-input.html.
При нажатии на кнопку show показывается наш модальный диалог. При этом, мы не можем мышкой перейти на поле ввода вне диалога или кликнуть по кнопке show еще раз до закрытия текущего. С первого взгляда все кажется вполне работоспособным. Но кажется это только до нажатия “магической” (magic!) кнопки tab. И тут мы попадаем на наши поля ввода в таком порядке:
- кнопка show;
- поле ввода за кнопкой show;
- поле ввода на диалоге
- кнопка hide;
- элементы управления браузера;
- и так по кругу…
Здесь мы видим, что модальный диалог никакой не модальный, а только кажется таковым.
Как это работает?Диалоги на HTML реализуются с помощью слоев отображения элементов. По умолчанию, у нас есть только один слой, т.е. свойство z-index у всех элементов одинаково и равно 0. Для создания нового слоя необходимо выставить свойство z-index в 1, 2, и т.д. В нашем примере, у элементов, не входящих в диалог, z-index равен 0, у фона диалога z-index равен 90, а его высота и ширина равняется 100%, что соответствует ширине и высоте окна браузера, из-за чего он визуально перекрывает элементы, у которых z-index < 90 и складывается впечатление модальности. Последним у нас идет элемент с содержимым диалога, у которого z-index равен 100 (максимальное, в нашем случае, значение), что позволяет нам отобразить его на “переднем” слоем.
Из-за слоев, мы не можешь попасть мышкой на кнопку show, но прекрасно можем добраться до нее с помощью клавиатуры (кнопка tab), а также вводить данные в текстовое поле вне диалога. Получается такой себе полу-модальный диалог с неправильной навигацией с клавиатуры.
В следующей части я расскажу как можно обойти данную проблему и покажу прототип модального диалога, в котором корректно работает tab order.