+7 495 008 8452 пн.-пт. 10:00 – 17:00
Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.


Стилизация полей веб-форм или других элементов страницы и AJAX

Многим наверно из нас приходилось на разрабатываемых сайтах стилизовать поля веб-форм или другие элементы страницы с помощью jQuery. Например, превращать обычный внешний вид системных полей в нечто подобное:

И редко сейчас какой сайт обходится без AJAX. Данную же статью хочу посвятить не тому, как выполнять стилизацию или как использовать на сайте AJAX, а тому, как научить их существовать вместе, т.е. речь пойдет о ситуации, когда вся стилизация полей как бы "слетает" после выполнения AJAX-запроса компонентом.


Например, это точно произойдет в одношаговом компоненте оформления заказа bitrix:sale.order.ajax. А "слетает" стилизация потому, что в определенном контейнере шаблона компонента происходит обычная замена html-кода, уже обработанного плагинами стилизации при первичном построении документа, на тот html-код, который приходит из AJAX-запроса. И т.к. большинство плагинов-стилизаторов сами по себе не умеют отслеживать изменения в структуре документа, то все обновленные элементы останутся в стандартном виде, из-за чего и создается впечатление, что стилизация "слетела".

На партнерском форуме обсуждался данный вопрос, и было предложено решение, которое мне не очень понравилось, поскольку оно требует дополнительной кастомизации шаблона плюс некоторого изменения логики штатного аякса (если я правильно понял автора). В общем, было предложено решение с переходом не на тот уровень, где на самом деле существует проблема, что впоследствии может усложнить поддержку проекта, поэтому решил поделиться своим вариантом решения.

Основная идея такова: всю динамическую стилизацию необходимо вынести в специальную функцию (назовем ее функция-стилизатор), чтобы в дальнейшем иметь возможность запускать ее на странице неопределенное количество раз. Вызываться она должна как минимум раз при первичном рендере страницы, а далее после каждого динамического изменения структуры документа, что обычно и делает AJAX. Для автоматизации запуска функции-стилизатора после AJAX-запросов, необходимо добавить обработчики специальных событий AJAX, которые имеются в jQuery: ajaxStart, ajaxSuccess, ajaxError, ajaxComplete, ajaxStop.

В общем, нет тут ничего такого, все довольно просто и банально, но почему-то на различных проектах мне приходится чаще сталкиваться именно с тем способом решения, который был предложен на форуме :) Ладно, идем дальше к реализации.

При реализации мы столкнемся с двумя проблемами. Первая - очень мало существует таких плагинов, которые умеют избегать повторной стилизации доверенных им элементов. Тем плагинам, которые этого не умеют, нужно будет дополнительно помочь. В общем случае проблем это вызвать не должно, т.к. задача легко решается простой фильтрацией с установкой или удалением специальных css-классов или с помощью jQuery.data(), но бывают и такие плагины, которые приходится дорабатывать напильником, чтобы добиться требуемого результата. Так что общего рецепта здесь, к сожалению, дать невозможно.
Вот пример частного решения для плагина "Uniform":
…
   StylizePageElements: function() {
      // стилизация полей веб-форм плагином "Uniform"
      // выбираем только те поля, у которых еще нет css-класса .stylized,
      // а каждому стилизованному полю добавляем css-класс .stylized
      jQuery('select, input:text, input:checkbox, input:radio, input:file').not('.stylized').each(function(){
         jQuery(this).uniform().addClass('stylized');
      });
   },
…

Здесь получилось все довольно просто и без напильника.

Ну и вторая проблема - штатная библиотека, которая используется для AJAX-запросов в компонентах, не имеет специальных AJAX-событий, таких как в jQuery. Но к счастью, в ней есть функции, которые отвечают за индикацию процесса AJAX-запроса: jsAjaxUtil.ShowLocalWaitWindow и jsAjaxUtil.CloseLocalWaitWindow, вот за них мы и зацепимся.

А цепляться будем так:



Из кода видно, что мы просто делаем копии штатных функций jsAjaxUtil.ShowLocalWaitWindow и jsAjaxUtil.CloseLocalWaitWindow, далее заменяем их код на свой, в котором, по сути, только добавляются специальные AJAX-события jQuery, чтобы свести все дальнейшее управление в одну точку, а штатные функции дальше запускаются через их копии.

Ну и в конечном итоге каркас у меня получился такой:




Если штатный способ индикации процесса не нужен, то каркас получится еще проще. В качестве развития идеи вызов стилизаторов можно повесить на обработчик своего кастомного события, чтобы иметь возможность динамически их добавлять или удалять (на практике это иногда бывает нужно).

Код подключается в шаблоне сайта отдельным js-файлом, либо прямо в теле (или как-то иначе), это уже каждый сам для себя решает.

Вот собственно и все. В завершении хочу отметить, что данный способ решает проблему не только для одного шаблона компонента, а сразу для всего сайта, без необходимости кастомизации шаблонов компонентов. Кроме того, он проще масштабируется, код сконцентрирован в одном месте и довольно просто переносится на другие проекты.

Исходники


P.S. Простите за код картинками, но оказывается на сайте разработчика CMS нельзя постить примеры js-кода...




Назад в раздел

Подписаться на новые материалы раздела:












CAPTCHA