Теперь буду кидать ссылку на эту статью, да и сам копипастить с неё при случае кусочки кода.
Задача
- Сделать форму «Перезвоните мне» во всплывающем окне.
- Не использовать самописных сниппетов MODx
- Форма должны быть быстрой, без всяких «отправить запрос на страницу и на js вырезать ответ».
Суть метода
Мы делаем плагин, в котором обрабатываем событие «Страница не найдена» (OnPageNotFound). В плагине вызываем через апи Modx сниппет FormLister, проверяем введённые данные, отсылаем письмо и возвращаем пользователю ответ.Всплывающую форму будем делать через библиотеку fancyBox.
Подготовка
Скачайте fancyBox и подключите к сайту. Для этого нужны всего 2 файла из дистрибутива, это jquery.fancybox.min.js и jquery.fancybox.min.css.Далее в тегах head пропишите пути к этим файлам. Например:
<link charset="utf-8" href="assets/templates/theme/vendors/fancybox/jquery.fancybox.min.css" rel="stylesheet" type="text/css" />
<script src="assets/templates/theme/vendors/fancybox/jquery.fancybox.min.js" charset="utf-8"></script>
Разумеется, также вам потребуется jQuery. Если он не подключен, то выше всех этих скриптов вызовите и его. Допустим, так:
<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
Теперь необходимо установить сам FormLister. Если вы не поставили его вместе с сайтом, то установить можно автоматически, в админке «Модули» — «Extras».
Вызов FormLister.
В нужном месте страницы разместите примерно следующее:<div class="callback-form" id="callback-form">
<div id="frmwrapper">
[!FormLister?
&formid=`form_callme`
&rules=`{"name":{"required":"Введите имя"},"phone":{"required":"Введите номер телефона","phone":"Введите номер правильно"}}`
&formTpl=`form_callme_tpl`
&messagesOuterTpl=`form_callme_outer`
&errorTpl=`form_callme_error_tpl`
&errorClass=` error`
&requiredClass=` error`
&to=`ВАША ПОЧТА`
&subject=`Запрос обратного звонка с сайта`
&reportTpl=`form_callme_report`
&successTpl=`form_callme_success`
!]
</div></div>
Сразу обращу внимание на то, что вместо чанков с шаблонами вы вполне можете вставить их содержимое сразу в сниппет, добавив в самом начале слово @CODE.
Например
&successTpl=`@CODE: <p>Спасибо за обращение</p>`
В нашем случае лучше всего воспользоваться чанками, так как код этих шаблонов нам будет нужен в дальнейшем, и незачем дублировать одну и ту же информацию в двух местах.
Содержимое чанков.
В чанке form_callme_tpl<form method="post" action="[~[*id*]~]#form_callme">
<input type="hidden" name="formid" value="form_callme">
<div class="row [+name.errorClass+] [+name.requiredClass+]">
<label>Ваше имя</label>
<input type="text" class="" placeholder="Как вас зовут?" name="name" value="[+name.value+]">
<span class="error">[+name.error+]</span>
</div>
<div class="row [+phone.errorClass+] [+phone.requiredClass+]">
<label>Ваш телефон</label>
<input type="text" class=" [+phone.errorClass+] [+phone.requiredClass+]" placeholder="Ваш номер телефона" name="phone" value="[+phone.value+]">
<span class="error">[+phone.error+]</span>
</div>
<button type="submit" class="submit">Заказать звонок</button>
[+form.messages+]
</form>
В чанки form_callme_outer и form_callme_error_tpl я вставил [+messages+] и [+message+] соответственно, т.к. мне не требовалось какое-то сильно навороченное сообщение об ошибках.
В form_callme_success сообщение об удачной отправке
<div class="alert-success">
<h3>Спасибо!</h3>
<p>Наш менеджер свяжется с вами в ближайшее время.</p>
</div>
Ну и form_callme_report это шаблон письма на почту
Письмо с сайта
Имя: [+name.value+]
Телефон: [+phone.value+]
По идее форма должна работать. Вы уже можете отправлять сообщения, получать предупреждения об ошибках и неверном вводе. Правда, страница будет перегружаться. Проверьте всё, прежде чем приступать к следующему шагу!
Делаем аякс-отправку.
Для того, чтобы содержимое формы отправлялось без перезагрузки, нам нужно немного js. Пишем похожий на этот скрипт:$(document).on('submit','#frmwrapper form',function(ev){
var frm = $('#frmwrapper form');
$.ajax({
type: 'post',
url: '/form_callme',
data: frm.serialize(),
success: function (data) {
$('#frmwrapper form').remove();
$('#frmwrapper').html( data );
}
});
ev.preventDefault();
})
При загрузке страницы скрипт ищет форму, заключённую в элемент с id=frmwrapper и заменяет событие отправки своей функцией. А именно: при отправке содержимое формы сериализуется и аяксом отправляется на урл form_callme. При ответе содержимое элемента c id=frmwrapper меняется на содержимое ответа.
Обратите внимание. frmwrapper — это id элемента-обёртки для формы. Выше, в вызове FormLister мы как раз его присвоили слою.
Форма
Теперь нам нужно сделать форму всплывающей. Для начала скроем слой с формой..callback-form {display: none;}
Теперь зададим кнопку, которая будет при клике открывать форму.
<a class="call" data-fancybox="" data-src="#callback-form" href="#">Заказать звонок</a>
Как видите, ссылка имеет необычные атрибуты data-fancybox="" data-src="#callback-form". Это как раз вызов модальной формы, расположенной в элементе с id=callback-form. Этот id мы также присвоили чуть выше, в коде вызова FormLister. Он может быть произвольным и при этом не должен повторяться.
Проверьте, всплывает ли форма. Зачастую вылезают ошибки, отследить их появление можно в консоли разработчика. Самая часто встречающаяся — jquery подключен после fancybox. Разумеется, в таком случае вы получите что-то типа fancybox is not defined.
Получаем и обрабатываем ajax
Как вы помните, мы сделали на js отправку данных на урл form_callme. Такого адреса на нашем сайте нет, и именно так всё и задумано. Делаем плагин.Назовите его как угодно, я назвал ajax. Перейдите на вкладку «Системные события» и отметьте чекбокс OnPageNotFound. Теперь содержимое:
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
return;
}
switch($_GET['q']){
case 'form_callme':
$result = $modx->runSnippet('FormLister', array(
'formid' => 'form_callme',
'rules' => '{"name":{"required":"Обязательно введите имя"},"phone":{"required":"Введите номер телефона","phone":"Введите номер правильно"}}',
'formTpl' => 'form_callme_tpl',
'messagesOuterTpl' => 'form_callme_outer',
'errorTpl' => 'form_callme_error_tpl',
'errorClass' => 'error',
'requiredClass' => 'error',
'to' =>'ВАШ ЕМАЙЛ',
'subject' => 'Запрос консультации с сайта',
'reportTpl' => 'form_callme_report',
'removeEmptyPlaceholders' =>'1',
'successTpl' => 'form_callme_success'
));
echo $modx->parseDocumentSource($result);
die();
break;
default:
die();
break;
}
Разберёмся. Скрипт сработает, когда кто-то запросил несуществующую страницу. Для начала скрипт проверяет, обратились ли к нему именно через ajax, или же просто кто-то открыл урл. Если всё хорошо, то получает данные GET-запроса и проверяет, искал ли кто-то урл form_callme. (В этом месте можно сделать ветвление для абсолютно разных запросов и выдавать наружу что угодно. Скажем, сделать 2-3 разных формы перезвона в зависимости от url и т. д. и т. п.
Потом через апи модх вызывается FormLister с аналогичными нашему первому вызову. Единственное, что добавилось, это параметр 'removeEmptyPlaceholders' =>'1' (необходимо для корректного отображения сообщений об ошибках)
Далее FormLister обрабатывает форму и выдаёт результат. Это могут быть как ошибки ввода так и успешная отправка формы. А мы получаем этот результат при помощи js-скрипта и показываем пользователю.
Проверяйте. Всё должно работать
Вараника 05.07.2017 13:42 #
Делаем такую же кнопочку отправки, прячем вызов формы ajaxForm в скрытый див, почти все как у автора статьи. При клике — DIV всплывает, ajaxform сделает все остальное.
Но, для тех, кто не нашел, как окошечко от фэнсибокс можно закрыть после отправки автоматически дополню Андрея.
В REVO (!)
Находим assets/components/ajaxform/js/default.js (в идеале — копируем и в системных настройках указываем новое имя).
Находим
И меняем / добавляем
Красоту и в REVO навели :)
Андрей Казунин 07.07.2017 11:55 #
В чанке successTpl добавить
Где 1000 — количество миллисекунд до закрытия.
Андрей [Aharitо́] Харитонов 03.12.2017 17:53 #
galaydas 11.12.2017 21:38 #
galaydas 11.12.2017 22:40 #
Sergey 14.02.2018 18:47 #
Андрей Казунин 15.02.2018 09:50 #
Андрей [Aharitо́] Харитонов 20.03.2018 13:01 #
Андрей [Aharitо́] Харитонов 20.03.2018 14:08 #
Затупил, однако :)
Андрей Казунин 20.03.2018 15:49 #
Можно сделать любой параметр и добавить его в вызов:
Сунуть его в defaultSource
И вывести в форме
Это если нужно что-то своё передать.
Стандартные поля Эво можно получать просто через defaultsSources:
А в шаблоне:
Андрей [Aharitо́] Харитонов 03.04.2018 06:28 #
Андрей [Aharitо́] Харитонов 22.03.2018 13:04 #
Стоит в reportTpl добавить абсолютную ссылку на страницу сайта, с которой была отправлена форма — эта ссылка из письма вырезается.
При этом письма с аналогичными ссылками через другой сниппет доходят.
Было у кого-либо такое?
Андрей [Aharitо́] Харитонов 02.04.2018 10:40 #
Андрей [Aharitо́] Харитонов 02.04.2018 10:45 #
Соответственно страница 404 перестаёт работать.
Код плагина надо поменять так:
Тогда все работает.
Андрей Казунин 02.04.2018 12:03 #
Андрей [Aharitо́] Харитонов 02.04.2018 18:41 #
Андрей Казунин 03.04.2018 10:55 #
Андрей [Aharitо́] Харитонов 03.04.2018 12:51 #
Дело в том, что HTTP_X_REQUESTED_WITH может быть и не пуст, но это всё равно не аякс-запрос.
У нас с вами используется логическое отрицание почти точной копии условия отсюда. А логическое отрицание «и» — это «или».
По сути можно было бы так:
Но чтобы код остался больше похожим на ваш, я сделал так:
Андрей Казунин 03.04.2018 13:09 #
Правда, теперь я делаю уже способом 4 все аяксы — отдельным файлом =) Надоедает плагин мучать, когда запросов много.
Андрей [Aharitо́] Харитонов 03.04.2018 17:30 #
А вы, если б написали примерчик ещё и с 4-м методом, то и себе баллы бы заработали. и людям благо сделали )))
Андрей Казунин 03.04.2018 17:31 #
Пишу, когда есть время.
Андрей [Aharitо́] Харитонов 03.04.2018 17:50 #