[spoiler]Для начала, несколько слов об изменениях, идущих в обновлении 6.5.6 Главного модуля.
Во-первых, исправлена ошибка, возникавшая в PHP 5.2.*. Исправление не связано с собственно Ajax 2.0, и результатом стало то, что теперь можно корректно использовать методы конкретных объектов в качестве обработчиков событий, задаваемых при помощи AddEventHandler, в расчете на то, что они будут выполнены в контексте объекта. Т.е., теперь можно использовать конструкцию вида:
class MyClass { var $my_property = 0; function __Handler() { $this->my_property++; } } $myObj = new MyClass(); AddEventHandler('main', 'onmyevent', array($myObj, '__Handler')); |
Во-вторых, добавлена экспериментальная возможность эмуляции поведения браузера при нажатии кнопок "Вперед" и "Назад". Это известная проблема AJAX-приложений, и мы не могли обойти ее своим вниманием. "Экспериментальная", потому что текущая реализация работает в IE и Mozilla Firefox, частично работает в Opera (с сильной зависимостью от версии) и совсем не работает в Safari. Она, также, не работает с формами, хотя с ними и сами браузеры не всегда и не все работают корректно. Работа над этой опцией продолжается и, я надеюсь, в скором времени эта пометка исчезнет из названия. Хотя, мне не хотелось бы повторять функционал известных библиотек наподобие
if (this.isSafari) { this.createSafari(); } else if (this.isOpera) { this.createOpera(); } |
Связанный с этим объект jsHistory я пока что описывать не буду, ограничусь только упоминанием того, что если вы хотите использовать его на локальном уровне AJAX, то нужно действовать таким образом:
1. при первом хите страницы вызвать jsHistory.init(node) (можно при window.onload), в качестве параметра передав идентификатор контейнера, чье состояние нужно запомнить как стартовое.
2. при каждом последующем обновлении содержимого контейнера нужно вызвать jsHistory.put(node). Параметр тот же.
3. отслеживание необходимости обновить содержимое контейнера из цепочки состояний и само обновление производятся автоматически.
В-третьих, несколько улучшено usablility настроек режима AJAX. Это еще не отражено в документации (по крайней мере, на момент написания поста), но изменилось следующее:
- флаги "отключить *" (дополнительные опции режима), заменены на "включить *", так что теперь нет такого неудобства, что включая флаг мы на самом деле отключаем какой-то функционал.
- соответственно, изменились названия параметров. Теперь вместо 'AJAX_OPTION_NO*' нужно использовать просто 'AJAX_OPTION_*'. Поскольку официально функционал еще в статусе "бета", то мы не стали заморачиваться проблемами совместимости, поэтому, если вы уже опробовали данную технологию, то поправьте параметры (руками или из формы настроек компонента).
Где оно сейчас будет работать?
На данный момент подтверждено соответствие режиму AJAX у компонентов bitrix:form и bitrix:main.profile. Могу по секрету сообщить, что компоненты bitrix:photo, bitrix:photo.detail и bitrix:voting.current также будут работать в этом режиме без каких бы то ни было изменений (по крайней мере, с шаблоном по умолчанию), хотя, обновлений по этим компонентам еще не выходило
По поводу собственных компонентов
А что я могу сказать по поводу ваших собственных компонентов? Нужно добавлять параметр AJAX_MODE в .parameters.php компонента и тестировать, смотреть. В документации это описано, но, пожалуй, повторю основные нюансы, на которые стоит обратить внимание.
1. не использовать в сценариях компонента document.write() в текущее окно; 2. следить за уникальностью CSS-стилей на разных страницах комплексного компонента. Это указано в руководстве по созданию компонентов 2.0, но все-таки повторю: стили, общие для страниц комплексного компонента, должны быть вынесены в стили компонента. Стили остальных страниц должны быть непересекающимися и используемыми только этой страницей; 3. следить за порядком выполнения клиентских сценариев компонента. Сценарии выполняются в строгом порядке, описанном ниже; 4. стоит делать так, чтобы ссылки, ведущие на страницы компонента, возвращающие не стандартный HTML-код, а, например, XML, не обрабатывались парсером. Типичный пример – ссылки, ведущие на RSS-ленту, создаваемую компонентом. То же самое стоит делать со ссылками, которые будут обработаны компонентом, но после обработки произойдет переадресация на другую страницу. Например, кнопка "купить" в компоненте bitrix:catalog. Это можно сделать, добавив ссылке атрибуты target="_self" или onclick="void(0)". |
- выполняется подключение всех внешних файлов сценариев; - выполняются сценарии, переданные непосредственно в коде ответа; - выполняются новые обработчики события window.onload. |
Дерзайте, с удовольствием жду примеров ваших компонентов, использующих технологию
И, напоследок, повторю здесь описание процесса кастомизации визуальных эффектов AJAX.
Этот пример описан в уже упоминавшейся выше
Стили визуальных эффектов AJAX располагаются в каталоге /bitrix/templates/.default/ajax. Соответственно, для простой модификации цветовой схемы достаточно скопировать этот каталог в каталог нужного шаблона и исправить цвета или заменить файлы изображений своими собственными. Мы же рассмотрим менее тривиальный вариант. Реализуем визуальный эффект AJAX-перехода в виде затенения всей страницы с выводом сообщения о загрузке в виде блока, расположенного посередине страницы.
Для этого, скопируем каталог со стилями визуализации в шаблон, для которого мы хотим модифицировать вывод. На скриншоте это шаблон web20 стандартной поставки. В каталог /bitrix/templates/__идентификатор_шаблона__/ajax/images скопируем картинку
iframe.waitwindowlocal {position:absolute; border:0px; z-index:9999;} div.waitwindowlocal {position:absolute; width:180px; padding:25px 5px 10px 5px; z-index:10000; background-color:#DADADA; border:1px solid #666666; background-image:url(images/progress.gif); background-position:center 7px; background-repeat:no-repeat; text-align: center; font-weight: bold; color: #666666; font-size: 9px;} div.waitwindowlocalshadow {position:absolute; top: 0px; left: 0px; height: 100%; width: 100%; z-index:9998; background-color: white;} div.waitwindowlocalshadow {opacity: 0.5; -moz-opacity: 0.5; -khtml-opacity: 0.5; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50);} |
Теперь очередь за кастомизацией сценария. Создадим каталог /bitrix/templates/__идентификатор_шаблона__/js и поместим в него файл customize_ajax.js со следующим содержимым:
if (window.jsAjaxUtil) { // переопределим метод jsAjaxUtil.ShowLocalWaitWindow() jsAjaxUtil.ShowLocalWaitWindow = function (TID, cont, bShadow) { if (typeof cont == 'string' || typeof cont == 'object' && cont.constructor == String) var obContainerNode = document.getElementById(cont); else var obContainerNode = cont; if (null == bShadow) bShadow = true; var container_id = obContainerNode.id; if (bShadow) { // если нужно отображать затенение - отобразим var obWaitShadow = document.body.appendChild(document.createElement('DIV')); obWaitShadow.id = 'waitshadow_' + container_id + '_' + TID; obWaitShadow.className = 'waitwindowlocalshadow'; if (jsAjaxUtil.IsIE()) { // для MSIE – раскроем тень по всей высоте содержимого окна obWaitShadow.style.height = document.body.scrollHeight + 'px'; } else { // для остального сделаем ее фиксированной obWaitShadow.style.position = 'fixed'; } } // создадим сообщение о загрузке var obWaitMessage = document.body.appendChild(document.createElement('DIV')); obWaitMessage.id = 'wait_' + container_id + '_' + TID; obWaitMessage.className = 'waitwindowlocal'; if (jsAjaxUtil.IsIE()) { // для MSIE – разместим его посередине текущего отображаемого контента окна var left = parseInt(document.body.scrollLeft + document.body.clientWidth/2 - obWaitMessage.offsetWidth/2); var top = parseInt(document.body.scrollTop + document.body.clientHeight/2 - obWaitMessage.offsetHeight/2); } else { // для остального сделаем ее посередине окна и с фиксированным положением var left = parseInt(document.body.clientWidth/2 - obWaitMessage.offsetWidth/2); var top = parseInt(document.body.clientHeight/2 - obWaitMessage.offsetHeight/2); obWaitMessage.style.position = 'fixed'; } obWaitMessage.style.top = top; obWaitMessage.style.left = left; // добавим текст obWaitMessage.innerHTML = 'Подождите, идет загрузка...'; if(jsAjaxUtil.IsIE()) { // для IE6 и ниже создадим под сообщением плавающий фрейм var frame = document.createElement("IFRAME"); frame.src = "javascript:''"; frame.id = 'waitframe_' + container_id + '_' + TID; frame.className = "waitwindowlocal"; frame.style.width = obWaitMessage.offsetWidth + "px"; frame.style.height = obWaitMessage.offsetHeight + "px"; frame.style.left = obWaitMessage.style.left; frame.style.top = obWaitMessage.style.top; document.body.appendChild(frame); } // добавим обработчик нажатия клавиши Esc. function __Close(e) { if (!e) e = window.event if (!e) return; if (e.keyCode == 27) { jsAjaxUtil.CloseLocalWaitWindow(TID, cont); jsEvent.removeEvent(document, 'keypress', __Close); } } jsEvent.addEvent(document, 'keypress', __Close); } } |
Как видно, мы переопределяем метод jsAjaxUtil.ShowLocalWaitWindow() под свои цели. Поскольку общая структура элементов остается прежней (см. оригинальный jsAjaxUtil.ShowLocalWaitWindow), то переопределять jsAjaxUtil.CloseLocalWaitWindow нам не требуется. Остается только подключить этот файл сценария в шаблон (файл /bitrix/templates/__идентификатор_шаблона__/header.php) так, чтобы он шел после подключаемой оригинальной библиотеки AJAX, то есть, после строки
<?$APPLICATION->ShowHeadScripts()?> |
вставить
<script src="/bitrix/templates/[i]__идентификатор_шаблона__[/i]/js/customize_ajax.js" type="text/javascript"></script> |
и можно просмотреть результат.
Внимание! Если нам не нужно полное изменение ShowLocalWaitWindow, то можно поступить проще:
if (window.jsAjaxUtil) { jsAjaxUtil._ShowLocalWaitWindow = jsAjaxUtil.ShowLocalWaitWindow; jsAjaxUtil.ShowLocalWaitWindow = function (TID, cont, bShadow) { if (null == bShadow) bShadow = true; jsAjaxUtil._ShowLocalWaitWindow(TID, cont, bShadow); /* И затем производим любые манипуляции с уже созданными объектами */ } } |
Post Scriptum. А что же дальше?
Я уже немного приоткрыл завесу над планами по дальнейшему развитию. Выложу несколько карт:
- уже указанная стабилизация эмуляции поведения браузера
- возможность устанавливать значения по умолчанию для дополнительных опций в .parameters.php компонента.
- ну и, собственно, приведение как можно большего числа стандартных компонентов к совместимости с режимом AJAX.
В плане отправки простых формочек, это понятно.
Но таких решений миллион.
Когда я могу подключить кастомный яваскрипт, который я уверен будет в десятки раз меньше с тем же функционалом.
Желательно бы описать для чего я должен разбираться в методах библиотеки, состоящих из 4 слов.
А еще бы посмотреть демо, где наиболее сложные и удачные моменты вашей библиотеки применены.