Форма заказа обратного звонка на MODX. Modx revo bootstrap
Как реализовать табы Bootstrap в MODX REVO + MIGX / modx.pro
Всего табов 6, 4 открытые, и 2 закрытые
Сначала хотел реализовать через pdoResources и каждому ресурсу присвоить поля для отображения в табах, но не получилось т.к. tabs Bootstrap(у) необходима связь между пангинацией (вкладками) и самим телом. А тело выполнено в виде контейнера с блоками (в моем случае ресурсами).
Вот код:
<div> <!-- табы --> <ul role="tablist"> <div></div> <li role="presentation"><a href="#level-1" aria-controls="level-1" role="tab" data-toggle="tab"><i></i><span>1 класс</span></a></li> </ul> <!-- табы(конец) --> <!-- Табы контент --> <div> <div role="tabpanel"> <div> <div> <div> <h3>Экспресс</h3> <p>100 <i aria-hidden="true"></i></p> <p><i aria-hidden="true"></i> 25 минут</p> <ul> <li>Мойка автомобиля напором воды без шампуня</li> </ul> <a href="#" role="button">Записаться</a> </div> </div> <div> <div> <h3>Экспресс "ПЛЮС"</h3> <p>200 <i aria-hidden="true"></i></p> <p><i aria-hidden="true"></i> 35 минут</p> <ul> <li>Мойка с использованием шампуня</li> <li>Без сушки кузова</li> </ul> <a href="#" role="button">Записаться</a> </div> </div> <div> <div> <h3>Стандарт</h3> <p>300 <i aria-hidden="true"></i></p> <p><i aria-hidden="true"></i> 45 минут</p> <ul> <li>Мойка с использованием шампуня</li> <li>Мойка порогов, арок колес, ковриков</li> <li>Сушка автомобиля</li> <li>Продувка воздухом</li> </ul> <a href="#" role="button">Записаться</a> </div> </div> <div> <div> <h3>Комфорт</h3> <p>400 <i aria-hidden="true"></i></p> <p><i aria-hidden="true"></i> 45-60 минут</p> <ul> <li>Мойка с использованием шампуня</li> <li>Мойка порогов, арок колес, ковриков</li> <li>Пылесос салона</li> <li>Сушка автомобиля</li> <li>Продувка воздухом</li> </ul> <a href="#" role="button">Записаться</a> </div> </div> </div> <div> <h4> <a role="button" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample" href=""> <span> <i aria-hidden="true"></i> </span> </a> </h4> <p>Дополниьельно</p> </div> <div> <div> <div> <div> <h3>Комплекс</h3> <p>550 <i aria-hidden="true"></i></p> <p><i aria-hidden="true"></i> 45-60 минут</p> <ul> <li>Мойка с использованием шампуня</li> <li>Мойка порогов, арок колес, ковриков</li> <li>Пылесос салона и багажника</li> <li>Чистка пластика (обделки салона)</li> <li>Мойка стекол изнутри</li> <li>Сушка автомобиля</li> <li>Продувка воздухом</li> </ul> <a href="#" role="button">Записаться</a> </div> </div> <div> <div> <h3>Престиж</h3> <p>750 <i aria-hidden="true"></i></p> <p><i aria-hidden="true"></i> от 60 минут</p> <ul> <li>Мойка с использованием шампуня</li> <li>Мойка порогов, арок колес, ковриков</li> <li>Пылесос салона и багажника</li> <li>Чистка пластика (обделки салона)</li> <li>Мойка стекол изнутри</li> <li>Чернение резины</li> <li>Покрытие воском</li> <li>Сушка автомобиля</li> <li>Продувка воздухом</li> </ul> <a href="#" role="button">Записаться</a> </div> </div> </div> </div> </div> </div>Можно попробовать реализовать в виде дополнительных полей, но это 5 классов машин, в каждом по 5 видов мойки, в каждом виде около 5-7 полей, это около 150 штук, просто не вариант такую грамотень городить)modx.pro
MODX - Создание шаблона для постов
На этом уроке мы создадим, а точнее напишем код для шаблона "Пост", который определяет структуру и внешний вид веб-страницы, содержащей пост.
В шаблоне «Пост» будем использовать следующие сниппеты:
- pdoCrumbs - для вывода «хлебных крошек»: (параметры сниппета: tpl - чанк для оформления ресурса в навигационной цепочке; tplWrapper – чанк-обёртка для навигационной цепочки; tplHome – чанк, для оформления ссылки на главную страницу; outputSeparator – строка, которая выступает в качестве разделителя между элементами в навигационной цепочке; showCurrent – булевский параметр, который определяет выводить текущий ресурс в хлебных крошках или нет; showHome – булевский параметр, который определяет выводить ссылку на главную страницу в начале навигации или нет). [[pdoCrumbs? &tpl=`@INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>` &tplWrapper=`@INLINE <ol>[[+output]]</ol>` &tplHome=`@INLINE <li><a href="/"><i></i></a></li>` &outputSeparator=`` &showCurrent=`0` &showHome=`1` ]]
- TicketMeta – для вывода информации о текущем посте. [[TicketMeta]]
- pdoNeighbors – для вывода ссылок на предыдущий и следующий посты от текущего (параметры сниппета: tplPrev – чанк, содержащий ссылку на предыдущий пост; tplNext - чанк, содержащий ссылку на следующий пост; tplWrapper – чанк, который является обёрткой для вывода ссылок на "соседние" посты).
[[pdoNeighbors?
&tplPrev=`@INLINE <span><li><a href="[[+link]]"><span></span> [[+menutitle]]</a></li></span>`
&tplNext=`@INLINE <span><li><a href="[[+link]]">[[+menutitle]] <span></span></a></li></span>`
&tplWrapper=`@INLINE <div><ul>[[+prev]][[+next]]</ul></div>`
]]
CSS код:
.neighbors { margin-bottom:10px; } - TicketComments – для вывода комментариев и формы для комментирования поста (параметр поста: allowGuest – булевский параметр, который позволять включить возможность комментирования для неавторизованных пользователей).
[[!TicketComments? &allowGuest=`1`]]
Для страниц, содержащих посты, будем использовать разметку, аналогичную главной странице.
- Открываем шаблон "Пост".
- Вводим следующий код: <!DOCTYPE html> <html lang="ru"> [[$chunk.head]] <body> <div> <div> [[$chunk.header]] [[$chunk.navbar]] <div> [[pdoCrumbs? &tpl=`@INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>` &tplWrapper=`@INLINE <ol>[[+output]]</ol>` &tplHome=`@INLINE <li><a href="/"><i></i></a></li>` &outputSeparator=`` &showCurrent=`0` &showHome=`1`]] <h2>[[*pagetitle]]</h2> [[*content]] [[TicketMeta]] [[pdoNeighbors? &tplPrev=`@INLINE <span><li><a href="[[+link]]"><span></span> [[+menutitle]]</a></li></span>` &tplNext=`@INLINE <span><li><a href="[[+link]]">[[+menutitle]] <span></span></a></li></span>` &tplWrapper=`@INLINE <div><ul>[[+prev]][[+next]]</ul></div>`]] [[!TicketComments? &allowGuest=`1`]] </div> <div> </div> </div> </div> [[$chunk.footer]] </body> </html>
itchief.ru
MODX - Форма обратной связи (FormIt)
Урок, на котором рассмотрим создание формы обратной связи в CMF MODX Revolution, используя компоненты AjaxForm и FormIt.
Назначение компонентов FormIt и AjaxForm
FormIt – это компонент (сниппет) для MODX Revolution, предназначенный для обработки формы на стороне сервера. Он может осуществлять проверку полей формы (валидацию) перед дальнейшими действиями, защищать сайт от получения спама, отправлять данные формы на почту, хранить копии заполненных форм, осуществлять редирект на другую страницу (например, после успешной отправки формы на email), выполнять функцию автоответчика и многое другое.
Но для того чтобы работать с FormIt через AJAX необходимо использовать дополнительный компонент AjaxForm.
Принцип работы формы обратной связи
Перед тем как перейти к разработке формы обратной связи в MODX Revolution, рассмотрим основной алгоритм её работы.
MODX - Схема работы формы обратной связиПосле открытия некоторой страницы с формой (она берётся из чанка, указанного в параметре &form вызова сниппета AjaxForm при формировании страницы на сервере), пользователь переходит к её заполнению. Завершив заполнение, пользователь нажимает на кнопку "Отправить" и компонент AjaxForm (код JavaScript) отправляет её на сервер посредством AJAX. На сервере данный компонент запускает сниппет FormIt и передаёт ему данные формы. Обработав эти данные, сниппет FormIt формирует ответ, который через компонент AjaxForm передаётся клиенту и отображается на странице пользователю. Ответ может быть положительным (это значит, что форма прошла валидацию и, например, данные были успешно отправлены на почту) или отрицательным (например, при заполнении формы пользователь допустил некоторые ошибки).
Создание формы обратной связи
Для создания формы обратной связи в MODX Revolution необходимо выполнить следующие основные шаги:
- Установить компоненты FormIt (из репозитория modx.com) и AjaxForm (из репозитория modstore.pro).
- Создать HTML форму в чанке (пример формы можно взять из чанка tpl.AjaxForm.example).
- Создать ресурс, в котором будет выводиться форма и шаблон. Подключить данный шаблон к ресурсу. MODX - Шаблон для ресурса Форма обратной связиMODX - Ресурс Форма обратной связи
- Добавить в созданный шаблон вызов сниппета AjaxForm и параметры, необходимые для его работы.
Рассмотрим шаги 2 и 4 более подробно.
Создание HTML формы в чанке
Создание HTML формы обратной связи можно осуществить посредством копирования заготовки tpl.AjaxForm.example. Например, присвоим скопированному чанку имя tpl.AjaxForm. Этот чанк, уже содержит готовую HTML-форму, состоящую из 3 полей: Имя, E-mail и Сообщение. Основные действия, которые надо производить с формой в основном будут сводиться к добавлению новых категорий или к удалению существующих. Под категорией будем понимать группу связанных между собой элементов: метка (label), элемент формы (input, select, textarea) и элемент span (используется для отображения ошибки валидации).
Основные моменты:
- Текст метки (элемента label). Обычно берётся либо из словаря (для многоязычных сайтов) или указывается непосредственно с помощью текста.
- Элемент span, должен иметь атрибут class со значением error_name, в котором фразу name необходимо изменить на значение атрибута name элемента формы, вслед за которым он расположен.
Внимание: использование плейсхолдера [[+fi.name]] в качестве значения атрибута value элемента формы и плейсхолдера [[+fi.error.name]] в качестве контента элемента span актуально только для классической работы с FormIt, т.е. без AJAX. Они используются для заполнения формы при её повторной отправке для того чтобы сохранить значения введённые пользователем и отобразить ошибки валидации.
Например, добавим в HTML форму поле для ввода телефонного номера:
<div> <label for="af_phone">Телефон:</label> <div> <input type="text" name="phone" value="" placeholder=""> <span></span> </div> </div>Создание кода, содержащего вызов сниппета AjaxForm
Открываем шаблон, который будет использовать ресурс и вводим код, который будет всё это осуществлять.
[[!AjaxForm? &form=`tpl.AjaxForm` &snippet=`FormIt` &hooks=`FormItSaveForm,email` &emailSubject=`Тестовое сообщение` &emailTo=`[email protected]` &emailFrom=`[email protected]` &emailTpl=`tpl.email` &validate=`name:minLength=^2^,email:email:required,message:minLength=^10^` &validationErrorMessage=`В форме содержатся ошибки!` &successMessage=`Сообщение успешно отправлено` ]]Разберём основные параметры:
- &form – отвечает за чанк, содержащий форму (tpl.AjaxForm).
- &snippet - сниппет, обрабатывающий форму (FormIt).
- &hooks – хуки, которые будет выполнять сниппет FormIt после успешной проверки формы (1 - FormItSaveForm, 2 - email). Хуки - это скрипты, которые запускаются после того когда форма прошла валидацию (проверку). Они указываются через запятую и запускаются последовательно один за другим. Если в одном из них произошла ошибка, то остальные не запускаются. В этом уроке будем использовать 2 хука. Хук FormItSaveForm предназначен для сохранения формы в базе данных. Хук email предназначен для отправки данных формы на почту.
- &emailSubject, &emailTo, &emailFrom, &emailTpl – параметры, значения которых использует хук email. Они предназначены для указания темы письма (&emailSubject), адреса отправки (&emailTo), заголовка From (&emailFrom), шаблона письма (&emailTpl).
- &validate – параметр, на основании значения которого осуществляется валидация формы. Значения параметра представляет собой список элементов, разделённых между собой запятыми. Каждый элемент состоит из имени элемента формы (который нужно проверить) и правила (требования к нему), разделённые между собой с помощью знака двоеточия. Например, валидатор name:minLength=^2^ проверяет, чтобы поле name содержало не меньше 2 символов. Валидатор email:email:required проверяет, чтобы поле mail содержало адрес электронной почты. С основными правилами создания валидаторов можно познакомиться на странице "FormIt Validators".
- &validationErrorMessage - содержит сообщение, которое будет выводиться, если в форме содержатся ошибки.
- &successMessage - сообщение, которое увидит пользователь, если сообщение будет успешно отправлено.
Осталось только создать чанк tpl.email, который будет содержать шаблон письма.
<h4>Сообщение</h4> <p>От кого: [[+name]]</p> <p>E-mail: [[+email]]</p> <p>Телефон: [[+phone]]</p> <p>Сообщение: [[+message]]</p> MODX - Чанк tpl.emailВнимание: Для вывода значений полей формы, используется плейсхолдеры.
Демонстрация работы формы обратной связи
Основные моменты при работе с формой обратной связи на странице продемонстрируем с помощью следующих изображений.
MODX - Незаполненная форма обратной связиMODX - Форма обратной связи, не прошедшая валидациюСообщение, об успешной отправке формыПросмотр заполненной формы в панели управления MODXПисьмо, пришедшее на почтовый ящикitchief.ru
Форма заказа обратного звонка на MODX Revo
Практически не один современный коммерческий сайт не обходится без формы заказа звонка. Сегодня мы рассмотрим как по быстрому создать форму заказа обратного звонка, ну и заодно рассмотрим как поместить данную форму в модальное окно. Реализовывать форму обратной связи мы будем при помощи пакета Formit в связке с пакетом AjaxForm, установите их если они у вас не установлены.
Создание формы заказа обратного звонка на MODX Revo с разрешением на обработку персональных данных в соответствии с законом №152-ФЗ «О персональных данных» от 27.07.2006.
Первым делом создаем чанк, в котором будет хранится сама форма, пусть это будет чанк «obr-zvonok» и помещаем в него код стандартной формы, я в основном делаю сайты с использованием bootstrap, так что возьму стандартную заготовку немного переделанную, ее статический код будет таким:
<form> <div> <input type="text" name="name" required="" placeholder="Ваше имя*" value=""> </div> <div> <input type="text" name="phone" required="" placeholder="Ваш телефон*" value=""> </div> <div> <label> <input type="checkbox" required=""> Согласен на обработку персональных данных </label> </div> <p>Ставя отметку, я даю свое согласие на обработку моих персональных данных в соответствии с законом №152-ФЗ «О персональных данных» от 27.07.2006 и принимаю условия <a href="#" rel="nofollow" target="_blank">Пользовательского соглашения</a></p> <div> <input type="submit" value="Жду звонка!"> </div> </form>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <form> <div> <input type="text" name="name" required="" placeholder="Ваше имя*" value=""> </div> <div> <input type="text" name="phone" required="" placeholder="Ваш телефон*" value=""> </div> <div> <label> <input type="checkbox" required=""> Согласен на обработку персональных данных </label> </div> <p>Ставя отметку, я даю свое согласие на обработку моих персональных данных в соответствии с законом №152-ФЗ «О персональных данных» от 27.07.2006 и принимаю условия <a href="#" rel="nofollow" target="_blank">Пользовательского соглашения</a></p> <div> <input type="submit" value="Жду звонка!"> </div> </form> |
Вот здесь вы можете посмотреть другие формы getbootstrap.com/css/#forms
Переделаем его в динамический:
<form method="post"> <div> <input type="text" name="name" required="" placeholder="Ваше имя*" value="[[+fi.name]]"> <span>[[+fi.error.name]]</span> </div> <div> <input type="text" name="phone" required="" placeholder="Ваш телефон*" value="[[+fi.phone]]"> <span>[[+fi.error.phone]]</span> </div> <div> <label> <input type="checkbox" required=""> Согласен на обработку персональных данных <span></span> </label> </div> <p>Ставя отметку, я даю свое согласие на обработку моих персональных данных в соответствии с законом №152-ФЗ «О персональных данных» от 27.07.2006 и принимаю условия <a href="[[~48]]" rel="nofollow" target="_blank">Пользовательского соглашения</a></p> <div> <input type="submit" value="Жду звонка!"> [[+fi.success:is=`1`:then=`<div>[[+fi.successMessage]]</div>`]] [[+fi.validation_error:is=`1`:then=`<div>[[+fi.validation_error_message]]</div>`]] </div> </form>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <form method="post"> <div> <input type="text" name="name" required="" placeholder="Ваше имя*" value="[[+fi.name]]"> <span>[[+fi.error.name]]</span> </div> <div> <input type="text" name="phone" required="" placeholder="Ваш телефон*" value="[[+fi.phone]]"> <span>[[+fi.error.phone]]</span> </div> <div> <label> <input type="checkbox" required=""> Согласен на обработку персональных данных <span></span> </label> </div> <p>Ставя отметку, я даю свое согласие на обработку моих персональных данных в соответствии с законом №152-ФЗ «О персональных данных» от 27.07.2006 и принимаю условия <a href="[[~48]]" rel="nofollow" target="_blank">Пользовательского соглашения</a></p> <div> <input type="submit" value="Жду звонка!"> [[+fi.success:is=`1`:then=`<div>[[+fi.successMessage]]</div>`]] [[+fi.validation_error:is=`1`:then=`<div>[[+fi.validation_error_message]]</div>`]] </div> </form> |
Теперь создаем еще один чанк, который будет формировать письмо, назовем его tpl-obr-zvonok со следующим содержимым:
<h4>Позвоните клиенту, он заказал обратный звонок:</h4> <p>Имя: [[+name]]</p> <p>Телефон: [[+phone]]</p>
<h4>Позвоните клиенту, он заказал обратный звонок:</h4> <p>Имя: [[+name]]</p> <p>Телефон: [[+phone]]</p> |
Ну и сталось сделать вывод в нужном месте:
[[!AjaxForm? &snippet=`FormIt` &form=`obr-zvonok` &emailTpl=`tpl-obr-zvonok` &hooks=`spam,email` &emailSubject=`Заказ обратного звонка с сайта [[++site_url]]` &emailTo=`[email protected]` &validate=`name:required,phone:required` &validationErrorMessage=`В форме содержатся ошибки!` &successMessage=`Сообщение успешно отправлено!` ]]
[[!AjaxForm? &snippet=`FormIt` &form=`obr-zvonok` &emailTpl=`tpl-obr-zvonok` &hooks=`spam,email` &emailSubject=`Заказ обратного звонка с сайта [[++site_url]]` &emailTo=`[email protected]` &validate=`name:required,phone:required` &validationErrorMessage=`В форме содержатся ошибки!` &successMessage=`Сообщение успешно отправлено!` ]] |
Не забудьте заменить email.
Документация по компонентам:
- FormIt — docs.modx.com/extras/revo/formit
- AjaxForm — docs.modx.pro/components/ajaxform
Форма заказа обратного звонка на MODX Revo в модальном окне.
Тут в принципе все просто, за основу берем тот же bootstrap:
<!-- Button trigger modal --> <button type="button" data-toggle="modal" data-target="#myModal"> Заказать звонок </button> <!-- Modal --> <div tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div role="document"> <div> <div> <button type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h5>Modal title</h5> </div> <div> ... </div> <div> <button type="button" data-dismiss="modal">Close</button> <button type="button">Save changes</button> </div> </div> </div> </div>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!-- Button trigger modal --> <button type="button" data-toggle="modal" data-target="#myModal"> Заказать звонок </button>
<!-- Modal --> <div tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div role="document"> <div> <div> <button type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h5>Modal title</h5> </div> <div> ... </div> <div> <button type="button" data-dismiss="modal">Close</button> <button type="button">Save changes</button> </div> </div> </div> </div> |
Кнопку выводим в нужном месте:
<button type="button" data-toggle="modal" data-target="#myModal">Заказать звонок </button>
<button type="button" data-toggle="modal" data-target="#myModal">Заказать звонок </button> |
Для модального окна создаем отдельный чанк и помещаем в него код модального окна и вызова самой формы:
<!--noindex--> <div tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div role="document"> <div> <div> <button type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h5>Оставьте Ваши контакты:</h5> </div> <div> <div> [[!AjaxForm? &snippet=`FormIt` &form=`obr-zvonok` &emailTpl=`tpl-obr-zvonok` &hooks=`spam,email` &emailSubject=`Заказ обратного звонка с сайта [[++site_url]]` &emailTo=`[email protected]` &validate=`name:required,phone:required` &validationErrorMessage=`В форме содержатся ошибки!` &successMessage=`Сообщение успешно отправлено!` ]] </div> </div> </div> </div> </div> <!--/noindex-->
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <!--noindex--> <div tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div role="document"> <div> <div> <button type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h5>Оставьте Ваши контакты:</h5> </div> <div> <div> [[!AjaxForm? &snippet=`FormIt` &form=`obr-zvonok` &emailTpl=`tpl-obr-zvonok` &hooks=`spam,email` &emailSubject=`Заказ обратного звонка с сайта [[++site_url]]` &emailTo=`[email protected]` &validate=`name:required,phone:required` &validationErrorMessage=`В форме содержатся ошибки!` &successMessage=`Сообщение успешно отправлено!` ]] </div> </div> </div> </div> </div> <!--/noindex--> |
Ну и выводим этот чанк ближе к закрытию body.
Вот в принципе и все!
web-revenue.ru
Урок 18. Создание галереи в MODX Revolution MODX
Всем привет. Сегодня в этом уроке я расскажу как создать галерею в MODX Revolution с помощью Twitter Bootstrap Image Gallery и дополнений FileDir (для вывода изображений) и PhpThumbOf (для создания миниатюр изображений).
Bootstrap Image Gallery это расширение диалога Modal набора Twitter Bootstrap для облегчения навигации между изображениями галереи. Она поддерживает навигацию мышью и клавиатурой, присутствуют эффекты при смене изображения, полноэкранный режим и слайдшоу.
Загрузка и установка необходимых ресурсов
Скачайте в репозитории MODX и установите дополнения PhpThumbOf и FileDir через Управление дополнениями менеджера. Далее скачайте Bootstrap Image Gallery файлы, распакуйте их и залейте на ваш сервер с сайтом в соответствующие папки, например: assets/css, assets/js, assets/img.
Загрузите изображения галереи на сервер в удобную для вас папку, например: assets/gallery/
После загрузки всех необходимых ресурсов, дерево файлов будет иметь следующий вид:
Создание шаблона
- Берём стандартный базовый шаблон MODX - Base template.
- Добавляем в тег HEAD необходимые стили:
- Добавляем в тег HEAD необходимые скрипты:
- Помещаем в тег BODY всплывающий модуль галереи:
- Делаем вызов сниппета FileDir и указываем для него путь к галерее, где содержаться изображения:
- Шаблонируем вывод отдельного изображения сниппета FileDir - создаём чанк photofile.tpl. Код чанка:
- Конечный шаблон:
Всё. Создание MODX Twitter Bootstrap галереи закончено.
Демо
При создании статьи использовались материалы:
- Галерея изображений Bootstrap
- Сниппет FileDir Валентина Расулова aka valikras
modx.ws