Как бы рутинно не выглядел процесс разработки Web-документов, он всё равно является творческим: нет ничего интереснее, чем придумывать формы представления информации, упрощать процесс взаимодействия пользователя с ней, склонять читателей к чтению текстов, а писателей — к их немедленному написанию. Пожалуй, это и есть Web как среда обмена информацией. А что если нам, как инженерам, разделить на низком уровне слои представления информации? Такой хитрый ход позволит обеспечить лёгкую модификацию ранее разработанных документов, не прибегая к прямому вмешательству в организацию документа: всё будет проходить достаточно прозрачно и просто.
Давайте попробуем сегодня достичь подобного результата. Думаю, что у нас всё получится (впрочем, как всегда).
Теоретические изыскания
Как же можно облегчить жизнь тому, кто хочет каким-либо образом изменить, дополнить или перекроить Web-документы? Можно попробовать разделить документ на слои, чтобы легче было работать с каждым из них. Чтобы легче было понять смысл слоёных документов, представим себе следующую картину: у нас есть документ, содержащий в себе заголовок, основную часть и подвал. Мы хотим добавить к заголовку ещё и подзаголовок, но у нас сложилась такая ситуация, что мы не можем напрямую изменить содержимое документа (например, мы пишем расширение Firefox, или скрипт Greasemonkey и подобные) или нам нужно ненавязчиво расширить функциональность какого-то блока нашего документа (например, в экспериментальных целях). В обычной ситуации, мы бы перебирали всё DOM-дерево, чтобы добраться до нужного нам узла, после этого использовали ещё дюжину DOM-функций для дополнения искомого элемента до нужного нам представления. Согласитесь, что выполнять такое каждый раз — достаточно утомительное занятие. Как же избежать подобного?
Сделаем так: на основной странице ключевые элементы обычно всегда определяются по атрибуту id. Этим мы и воспользуемся: будем через AJAX подгружать нужный нам XML-файл, в котором будет описание слоя-настилки на наш документ. Посмотрим пример такого слоя:
Данный слой накладывается на элемент с атрибутом id, равным header после всех существующих там элементов (атрибут insert со значением end). Само содержимое нового слоя содержится в специальном элементе CDATA, чтобы парсер не воспринимал всё содержимое элемента как XML, а считал его обычным текстом (при этом обязательно использование атрибута type со значением plain). С другой стороны, мы можем записывать содержимое слоя-настилки в виде XML, но тогда потребуется дополнительная процедура обработки содержимого слоя-настилки для превращения всех XML-элементов в XHTML-элементы.
Посмотрим на наш основной документ:
Всё становится предельно понятно: наш слой при наложении на документ образует симбиоз элементов, изменяя структуру документа до нужной нам:
Маленькая деталь: предыдущий пример немного лукавит, так как перед тем, как наложить слой на документ, он оборачивается в элемент div с установленным атрибутом id для того, чтобы позже можно было бы проводить операции с данным слоем (удалять, например).
Что-ж, перейдём к практической части нашего повествования.
Практические изыскания
Сделаем для нашей теории небольшую практическую реализацию в качестве примера. Назовём наш класс-синглтон JSOverlay и создадим для него отдельное пространство имён:
Далее, нам понадобится ассоциативный массив для хранения загруженных слоёв (чтобы их можно было контролировать после загрузки):
Мы уже сейчас можем реализовать метод для получения слоя (или слоёв, так как одному элементу может быть назначено несколько слоёв):
Опишем класс слоя, чтобы было легче управлять столь одинаковыми сущностями:
Нам понадобится структура информации о слое, которая должна состоять из имени слоя, его типа и позиции. Создадим её:
Чтобы не разбрасывать ассоциированные элементы, заключим их также в одну структуру:
Вслед за этим, реализовываем методы, необходимые для утилизации возможностей слоя:
И ещё один метод, для отделения нового слоя от исходного элемента:
Заметьте, что мы не удаляем весь слой, а только то, что он внедряет на страницу. Осталось только завершить наш класс:
Двигаемся дальше. Теперь нам нужен метод уже пространства имён JSOverlay для загрузки нашего слоя. По сути, мы разделим данный метод на два метода: собственно загрузка и обработка XML-данных вместе с созданием, добавлением и активацией слоя. Начнём с загрузки через XMLHttpRequest (нет ничего проще):
Понятно, что с помощью вышеописанного метода мы сможем загружать слои как JSOverlay.LoadOverlay("overlay/my.xml");. Естественно, путь, который загружается с помощью данного метода, должен существовать, иметь Content-Type text/xml (или один из подобных) и содержать в себе валидный и соответствующий XML.
Мы не реализовали последний метод, сделаем же это:
Готово! Всё, что получилось, можно посмотреть на странице-примере, открыв её исходные коды.
Что можно добавить?
Чтобы облегчить себе жизнь в некоторых ситуациях, можно превратить overlay.js в какой-нибудь серверный скрипт, который будет генерировать JavaScript-код для подключения разных слоёв. К примеру, можно сделать так: при обращении к /overlay/add/ генерируется JavaScript для подключения слоя с именем
Выводы
Представленный прототип уже сейчас может выполнять возложенные на него обязанности, но его можно расширять до бесконечности: поддержка стилей, встроенных в расширение скриптов (хотя, этого можно достичь, просто прописав в нём элемент script, который будет подключать внешний файл с кодом), дерева DOM (для поиска элементов не только по id, но и по другим отличительным чертам, например, по атрибуту class или и вовсе по произвольному атрибуту элементов). Можно даже периодически заглядывать на вышеуказанную страницу с примером, так как иногда там будет появляться новая версия небольшого скрипта.
Как всегда, в конце записи желаю моим читателям хорошего настроения на все выходные.