Продолжение предыдущего поста: http://blog.e0ne.info/post/Modal-popup-with-HTML.aspx
Часть 2. Практика
Если есть проблема, то, обязательно, должно быть решение. Так как готового я не нашел (возможно, плохо искал), пришлось изобретать свое. Решений, на самом деле, нашлось аж целых два, но так как я остановился лишь на одном, то это решение я рассмотрю более подробно и с примером.
Для начала рассмотрю тот вариант, который я не стал реализовывать.
Решение проблемы #1: манипуляции с свойством tabIndex.
Те, кто сталкивался с необходимостью навигацией по сайту с помощью клавиатуры непременно сталкивались с таким свойством элементов, как tabIndex. По умолчанию, для всех элементов (кроме ) и tabIndex равен 0. Для других элементов свойство или не определено, или задано значение “-1” (минус еденица) В таком случае переход по элементам осуществляется в порядке их расположения в DOM-моделе. Если необходимо сделать так, чтоб при навигации по странице с помощью кнопки tab фокус на элемент не попадал, то значение tabIndex необходимо сделать -1.
Исходя из вышесказанного, можно сделать такой алгоритм создания модального окна:
- реализовать диалоговое окно, как описано в предыдущем посте;
- при вызове функции show() для всех элементов запоминаем текущее состояние tabIndex и ставим новое значение, равное “-1”;
- в вызове функции hide() восстанавливаем прежние значения tabIndex.
Так как этот способ на практике я не реализовывал, то не могу сказать какие проблемы он может вызвать.
Решение проблемы #2: манипуляции с DOM.
Мой диалог работает следующим образом: базовая часть отображения остается без изменений, все изменения касаются только функций show и hide и некоторыми манипуляциями в DOM-модели.
Работает это следующим образом:
Соответственно, в методе hide() необходимо все вернуть на своё место:
- убираем атрибут disabled:$('#body-container').removeAttr(‘disabled’);
- ставим диалог на то место, где он находился изначально; для этого нам и нужна была метка:$("#dlg-content").insertAfter($("#dlg-marker"));
- удаляем ранее созданную метку:$("#dlg-marker").detach();
- удаляем элемент, в который мы поместили содерживое body:var html = $('#body-container').html();$('#body-container').detach();$(document.body).html(html);
- прячем диалог.
Этот код является слишком неоптимизированным - от него можно избавится, если элемент будет находится на странице всегда.
Манипуляции с возвращением диалога на прежнее место, прежде всего, необходимы для корректной работы приложений, написанных с помощью ASP.NET. Если этого не сделать, то будут проблемы c UpdatePanel и кнопками, которые находятся вне формы.
В файле advanced-popup-with-input.html я привожу базовую реализацию такого способа. Для использования в production его необходимо немного доработать напильником. А именно:оформить это всё в виде плагина для jQuery или виджета jQueryUi;решить проблему с производительностью и обработчиками событий при возвращении элементов в начальное положение относительно DOM-модели.
Сейчас похожая реализация успешно работает в production коде, единственное отличие состоит в том, что элемент всегда находится на странице и нет необходимости его добавлять и удалять.
Все примеры доступны на GitHub: https://github.com/e0ne/BlogSamples/tree/master/ModalDialog