Многим наверно из нас приходилось на разрабатываемых сайтах стилизовать поля веб-форм или другие элементы страницы с помощью jQuery. Например, превращать обычный внешний вид системных полей в нечто подобное:
И редко сейчас какой сайт обходится без AJAX. Данную же статью хочу посвятить не тому, как выполнять стилизацию или как использовать на сайте AJAX, а тому, как научить их существовать вместе, т.е. речь пойдет о ситуации, когда вся стилизация полей как бы "слетает" после выполнения AJAX-запроса компонентом. [spoiler]
Например, это точно произойдет в одношаговом компоненте оформления заказа 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-файлом, либо прямо в теле (или как-то иначе), это уже каждый сам для себя решает.
Вот собственно и все. В завершении хочу отметить, что данный способ решает проблему не только для одного шаблона компонента, а сразу для всего сайта, без необходимости кастомизации шаблонов компонентов. Кроме того, он проще масштабируется, код сконцентрирован в одном месте и довольно просто переносится на другие проекты.
А я считаю что стилизация полей формы это первая ошибка юзабилити. Пользователям и так тяжело даются web интерфесы для понимания, а тут еще стандартные и вроде как понятные контролы начинают разукрашивать. Единственно что я могу допустить эти динамический селект с поиском.
Или подобные со специальным функционалом, но и то это нужно делать очень аккуратно. Вообще понятность сайта для пользователя играет гораздо большую роль в успешности проекта чем вы думаете.
Согласен с тем, что нефигменять стандартные контролы. Еще ж важный момент: они в итоге в среде, на которую не рассчитывали, смотрятся совершенно идиотски, типа имитация маковских контролов в Windows... Другое дело, что безумные дизайнеры о таких вещах не думают обычно.
Имхо, проблема шире, так как в обновляемом AJAX участке может быть подключена не только стилизация, но и различные функциональные скрипты, которые повторно не навесятся. Решаем повторным подключением в обновляемом участке.
Я сам ярый противник изменений интерфейса полей веб-форм, но иногда этого требует клиент. Да и стилизация полей - это лишь один из примеров, бывает много еще чего нужно делать динамически, например, добавлять скругления или менять шрифты на "более красивые".
Коллеги, да ладно вам. Иногда чуток приятнее контролы сделать хорошо. Или давайте теперь всю жизнь тащить на себе убогий груз 90-х что ли? Любой элемент должен гармонично вписываться в контекст и сам за себя говорить "кликни по мне" или "а меня можно раскрыть".
Другое дело, что контролы должны продолжать работать, если отсутствует JS, точнее браузер не позволяет управлять кастомными контролами. А то зашел с телефона на один сайт и не смог воспользоваться фильтром - кастомизация в телефоне отобразилась, а вот управлять списком уже нельзя было.
Сделал акцент на jsAjaxUtil, т.к. он пока еще используется в компонентах и за него немного сложнее зацепиться. В большей степени пост базировался на примере решения проблемы с компонентом bitrix:sale.order.ajax.
А для "нового" аякса тоже есть пример - он в самом низу, закомментирован. Но лично я очень скептически отношусь к новой библиотеке битрикса, не рассматриваю ее пока как инструмент, которым можно и нужно пользоваться. Она громоздкая, неудобная, скудная по функционалу и вдобавок не имеет документации. Например, первая проблема, с которой мы можем с ней столкнуться - это отсутствие события onAjaxStart, но надеюсь, что это я просто не нашел или его вскоре добавят.
Он о том и говорит -- юзер именно такие элементы видит везде и привык, что "вот тут" можно кликнуть, а "это вот" раскрывается. А тут ему бац -- и продукт творческой жизнедеятельности дизайнера под нос суют 8)
Да, интересное решение. Но это плюс запрос к серверу и все та же правка шаблонов. Еще не уверен, что в Опере будет работать всегда как надо, она иногда на кэшированные картинки onload не создает. По крайней мере так было в ранних версиях.
Обычно приятное на вид - не означает полностью функциональное. Например, я еще не видел готовых плагинов для стилизации списков (<select>), полностью повторяющих функционал стандартных полей. Так чтобы и направление по оси Y меняли, и группы поддерживали, и автопоиск нормальный имели, и множественный выбор поддерживали, и управление клавишами, при этом не тормозили и легко кастомизировались. Всегда чего-то да не хватает. У меня сайты, которые имеют "дизайнерские" контролы, часто создают ощущение какой-то ненадежности, всегда думаешь, сейчас вот тут нажмешь и оно сломается. Что часто и случается.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».