Не помогло, помогла только эта
статья, я не знаю кто её точно писал.
Опишу, что в ней (для тех кто боится ходить по незнакомым сайтам или лимит):
--
Что необходимо получить:
* поля проверяются «на лету» (по мере заполнения пользователем формы);
* использование каптчи;
* возможность отправить сообщение, только когда все поля заполнены верно.
Для работы с формой воспользуемся сниппетом
eForm, для проверки полей на лету будем использовать
JavaScript. Итак, приступим.
Для начала создадим новый документ, в котором у нас будет отображаться форма обратной связи. Назовем его «Обратная связь» и в содержимое запишем следующее:
<h1>Обратная связь</h1>
[!nikoFeedBack]]
Последняя строчка —
некэшируемый вызов сниппета
nikoFeedBack, который и отвечает за вывод нашей формы.
Теперь создаем новый сниппет: название — «
nikoFeedBack», описание — «
Форма обратной связи».
Код сниппета:
<?php
function fbValidateName($value) { return strlen($value)>=5; }
function fbValidateText($value) { return strlen($value)>=15; }
$modx->regClientStartupScript($modx->config['site_url'].'assets/snippets/nikoFeedBack/validate.js');
$outForm = $modx->runSnippet(
"eForm",
array(
"formid" => "FeedBackForm",
"to" => "[email protected]",
"tpl" => "eFBForm",
"report" => "eFBReport",
"thankyou" => "eFBThanks",
"from" => "[+fbEMail+]",
"fromname" => "site.ru",
"subject" => "Посетители сайта пишут",
"vericode" => "1"
)
);
echo $outForm;
?>
В начале сниппета задается две функции:
fbValidateName и
fbValidateText. Они отвечают за проверку корректности введенных данных полей «
Имя» и «
Текст сообщения». Откуда эти функции вызываются — опишу позднее.
Затем с помощью стандартной функции в MODx
regClientStartupScript добавляем скрипт validate.js (в нем будут храниться скрипты, отвечающие за проверку введенных значений на лету) для загрузки внутрь тега <head>.
Далее вызывается сниппет
eForm, который используется для работы с формами в
MODx. При вызове сниппета передаем ему следующие параметры:
*
formid – Идентификатор формы, который используется при отправке данных («FeedBackForm»).
*
to -
Адрес Email на который будет послана информация. Можно использовать несколько адресов разделяя их запятой (,). Если не указано, то будет использован системный адрес. В данном случае информация будет отправлена на адрес
[email protected].
*
tpl - Название чанка (не число) или идентификатор документа (число) для используемого шаблона. Наш чанк с формой будет называться «
eFBForm».
*
report - Название чанка (не число) или идентификатор документа (число) для шаблона отчета. Это шаблон для письма, которое будет отправлено с сайта к нам на почту, у нас он называется «eFBReport».
*
thankyou - Название чанка (не число) или идентификатор документа (число) для используемого шаблона сообщения выводимого пользователю после отправки данных формы. Наш чанк с благодарностью пользователю за оставленное сообщение будет называться «
eFBThanks».
*
from - Устанавливает адрес отправителя письма. В качестве адреса устанавливаем плейсхолдер
[+fbEMail+], который будет содержать адрес электронной почты пользователя.
*
fromname - Устанавливает имя отправителя письма. Пишем название нашего сайта, чтобы видеть сразу откуда письмо.
*
subject - Тема письма. Для примера поставим «Посетители сайта пишут».
*
vericode - Включает использование каптчи в форме.
Перейдем к чанкам. Для начала создадим чанк
eFBForm, содержащий форму.
<p>Пишите сообщения и не сомневайтесь - вы будете услышаны!</p>
<div class="fbForm">
<p><span style="color:#900;">[+validationmessage+]</span></p>
<form method="post" action="[~[*id*]~]" id="FeedBackForm">
<div class="form">
<div class="name">Ваше имя и фамилия</div>
<div class="error" id="fbNameError"></div>
<div class="element"><input type="text" name="fbName" id="fbName" eform="Имя::1:Должно содержать не менее 5 символов.:#FUNCTION fbValidateName" value="[+fbName+]"></div>
<div class="name">Адрес электронной почты</div>
<div class="error" id="fbEMailError"></div>
<div class="element"><input type="text" name="fbEMail" id="fbEMail" eform="EMail:email:1:EMail » Некорректный адрес электронной почты." value="[+fbEMail+]"></div>
<div class="name">Текст сообщения</div>
<div class="error" id="fbTextError"></div>
<div class="element"><textarea name="fbText" id="fbText" eform="Текст сообщения:html:1:Должен содержать не менее 15 символов.:#FUNCTION fbValidateText" cols="40" rows="5">[+fbText+]</textarea></div>
<table cellpadding="0" cellspacing="0" class="captcha-test">
<tr>
<td>
<div class="name">Защита от спама</div>
<div class="captcha"><img src="[+verimageurl+]" alt="Проверочный код" border="1"></div>
</td>
<td>
<div class="name">Код на картинке:</div>
<div class="element"><input type="text" name="vericode" id="vericode" value=""></div>
</td>
</tr>
</table>
<div class="submit"><input type="submit" name="fbSubmit" id="fbSubmit" value="Отправить"></div>
</div>
</form>
</div>
[+validationmessage+] - этот плэйсхолдер выводит ошибки, если данные, отправленные на сервер, были некорректными или отправка сообщения не удалась.
[+verimageurl+] - плэйсхолдер содержит адрес картинки с каптчей. Для проверки каптчи — необходимо использовать INPUT c именем «vericode».
Пустые слои с идентификаторами <имя поля>Error — используются для вывода ошибок при заполнении полей, когда проверка данных проводится «на лету».
Как вы заметили поля формы имеют дополнительный параметр efrom. Он используется для настройки встроенного в eForm анализатора, определяющего формат и тип данных с соответствующей проверкой каждого поля. Базовый вид параметра eform следующий:
[description/title]:[datatype]:[required]:[validation message]:[validation rule]
description/title — Название (описание) поля.
datatype — Тип данных.
required – Обязательно ли заполнение этого поля.
validation message — Сообщение при неудачной проверке значения поля.
validation rule — Правило проверки значения поля.
Вот здесь мы и используем функции
fbValidateName и
fbValidateText, описанные в сниппете nikoFeedBack, для проверки корректности значений полей
«Имя» и «Текст сообщения».
Стили используемые в форме:
* { padding : 0px; margin : 0px; border: none; }
BODY {
color: #252525;
font-family: Tahoma, Arial, Helvetica, sans-serif;
font-size: 10pt;
}
.fbForm .form { padding-left: 40px; }
.fbForm .name { padding-top: 12px; font-size: 8pt; color: #7d7d7d; }
.fbForm .element { padding-top: 2px; }
.fbForm .element INPUT, .fbForm .element TEXTAREA {
border: 1px solid #ccc;
background-color: #E6EFF6;
font-size: 10pt;
color: #2C5883;
}
.fbForm INPUT#fbName,
.fbForm INPUT#fbEMail {
background-image: url(images/icon_form.gif);
background-repeat: no-repeat;
width: 250px;
padding: 4px 0px 4px 25px;
}
.fbForm INPUT#fbName { background-position:3px -3px; }
.fbForm INPUT#fbEMail { background-position:3px -33px; }
.fbForm TEXTAREA#fbText {
padding: 4px 4px 4px 25px;
width: 425px;
font-family: Tahoma;
background: #E6EFF6 url(images/icon_form.gif) no-repeat 3px -93px;
}
.fbForm .captcha-test TD { vertical-align: top; padding-right: 15px; }
.fbForm .captcha { padding-top: 3px; }
.fbForm .captcha IMG { border: 1px solid #ccc; }
.fbForm INPUT#vericode { width: 130px; padding: 4px 0px 4px 25px; background: #E6EFF6 url(images/icon_form.gif) no-repeat 3px -63px; }
.fbForm .submit { padding-top: 15px; }
.fbForm INPUT#fbSubmit {
border: 1px solid #ccc;
background-color: #f7f7f7;
cursor: pointer;
padding: 2px 15px 2px 15px;
}
.fbForm .error { font-size: 8pt; color: red; display: none; }
Создадим чанк
eFBReport, шаблон присланного письма:
<p>Поступило сообщение через обратную связь сайта <b>site.ru</b>.</p>
<p>
[+postdate+]
<br>
[+fbName+] ([+fbEMail+]) пишет:
</p>
----------------------------------------------
<p>
[+fbText+]
</p>
----------------------------------------------
<p>Для ответа можно использовать эту ссылку: <a href="mailto:[+fbEMail+]?subject=RE: site.ru">[+fbEMail+]</a></p>
Создадим чанк
eFBThanks, который используется после успешной отправки сообщения. Тут всё просто:
<p>Cообщение отправлено.</p>
<p>Благодаря вашей помощи проект может стать лучше!</p>
<p>Поступило сообщение через обратную связь сайта <b>site.ru</b>.</p>
<p>
[+postdate+]
<br>
[+fbName+] ([+fbEMail+]) пишет:
</p>
----------------------------------------------
<p>
[+fbText+]
</p>
----------------------------------------------
<p>Для ответа можно использовать эту ссылку: <a href="mailto:[+fbEMail+]?subject=RE: site.ru">[+fbEMail+]</a></p>
В чанке используются следующие плейсхолдеры:
[+postdate+] - дата отправки сообщения;
[+fbName+], [+fbEMail+], [+fbText+] - соответствующие поля формы.
На этом основную часть нашей формы мы сделали
Она уже вполне работоспособна. Корректность введенных данных проверяется на сервере. Теперь добавим в нашу форму немного динамичности. Что мы сделаем:
* проверка корректности введенных значений на лету;
* кнопка отправить будет доступна только когда все поля формы заполнены верно (за исключением каптчи — это проверяется на сервере всегда).
Создаем папку
nikoFeedBack в папке
assets/snippets/. Теперь в созданной папке создаем файл
validate.js. Содержание файла следующее:
var fbNowShowError; // Выводить ли при проверки поля ошибки
function fbIsFormValid() {
var formFeedBack = document.getElementById("FeedBackForm");
var result = true;
for (var i=0; i < formFeedBack.elements.length; i++) {
if (typeof formFeedBack.elements[i].valid == "boolean") {
result = result && formFeedBack.elements[i].valid;
}
}
return result;
}
function fbValidateField(txtField) {
var fbNameError = document.getElementById("fbNameError");
var fbEMailError = document.getElementById("fbEMailError");
var fbTextError = document.getElementById("fbTextError");
// Проверка имени
if (txtField.name == "fbName") {
if (txtField.value.length < 5) {
if (fbNowShowError) {
fbNameError.style.display = "block";
fbNameError.innerHTML = "Имя должно содержать не менее 5 символов";
}
txtField.valid = false;
} else {
if (fbNowShowError) {
fbNameError.style.display = "none";
}
txtField.valid = true;
}
}
// Проверка email
if (txtField.name == "fbEMail") {
var re = /^[\.\-_A-Za-z0-9]+?@[\.\-A-Za-z0-9]+?\.[A-Za-z0-9]{2,6}$/;
if (!re.test(txtField.value)) {
if (fbNowShowError) {
fbEMailError.style.display = "block";
fbEMailError.innerHTML = "Некорректный адрес электронной почты";
}
txtField.valid = false;
} else {
if (fbNowShowError) {
fbEMailError.style.display = "none";
}
txtField.valid = true;
}
}
// Проверка текста сообщения
if (txtField.name == "fbText") {
if (txtField.value.length < 15) {
if (fbNowShowError) {
fbTextError.style.display = "block";
fbTextError.innerHTML = "Текст сообщения должен содержать не менее 15 символов";
}
txtField.valid = false;
} else {
if (fbNowShowError) {
fbTextError.style.display = "none";
}
txtField.valid = true;
}
}
var fbSubmit = document.getElementById("fbSubmit");
if (fbIsFormValid()) {
fbSubmit.disabled = false;
fbSubmit.style.cursor = 'pointer';
} else {
fbSubmit.disabled = true;
fbSubmit.style.cursor = 'default';
}
}
function fbValidateFieldOnChange(oEvent) {
fbNowShowError = true;
oEvent = oEvent || window.event;
var txtField = oEvent.target || oEvent.srcElement;
fbValidateField(txtField);
}
function fbValidateFieldOnKeyUp(oEvent) {
fbNowShowError = false;
oEvent = oEvent || window.event;
var txtField = oEvent.target || oEvent.srcElement;
fbValidateField(txtField);
}
window.onload = function () {
var fbName = document.getElementById("fbName");
var fbEMail = document.getElementById("fbEMail");
var fbText = document.getElementById("fbText");
var fbVeriCode = document.getElementById("vericode");
var fbSubmit = document.getElementById("fbSubmit");
fbSubmit.disabled = true;
fbSubmit.style.cursor = 'default';
fbName.valid = false;
fbEMail.valid = false;
fbText.valid = false;
fbName.onchange = fbValidateFieldOnChange;
fbEMail.onchange = fbValidateFieldOnChange;
fbText.onchange = fbValidateFieldOnChange;
fbName.onkeyup = fbValidateFieldOnKeyUp;
fbEMail.onkeyup = fbValidateFieldOnKeyUp;
fbText.onkeyup = fbValidateFieldOnKeyUp;
fbNowShowError = true;
if (fbName.value != '') fbValidateField(fbName);
if (fbEMail.value != '') fbValidateField(fbEMail);
if (fbText.value != '') fbValidateField(fbText);
fbNowShowError = false;
fbVeriCode.value = '';
fbValidateField;
};
Кратко опишу, что делает каждая их функций:
fbIsFormValid — проверяет все ли поля формы заполнены правильно.
fbValidateField — проверяет правильно ли заполнено поле. Автоматически определяется тип поля — и проводится соответствующая проверка. По окончании проверки поля проверяется — правильно ли заполнены остальные поля, и если правильно — то кнопка «Отправить» становится доступной, если не правильно — то недоступной.
fbValidateFieldOnChange — функция, вызываемая при изменении поля (после потери им фокуса). Сама функция — вызывает функцию проверки поля.
fbValidateFieldOnKeyUp — функция, вызываемая каждый раз при изменении поля. Сама функция — вызывает функцию проверки поля.
Разные функции на события
OnChange и
OnKeyUp вызываются для того, чтобы задать - выдавать ли ошибку при проверке или нет. То есть, когда объект не потерял фокус, но произошло его изменение (событие
OnKeyUp) — производится проверка данного поля и всех остальных полей для того, чтобы в случае правильности заполнения сделать активной кнопку «Отправить», но при этом ошибки не выводятся, либо продолжают показываться. В случае же когда поле теряет фокус (событие
OnChange) помимо проверки — показывать или нет кнопку «
Отправить» - также показывается сообщение об ошибке в случае некорректных данных или исчезает ошибка, если данные введены верно. Довольно запутанно, но это необходимо, например, для того, чтобы при первоначальном заполнении полей — сразу не выскакивали ошибки (если разделения не будет, то как только мы начнем вводить к примеру Имя, то сразу вылезет ошибка).
В конце с помощью конструкции
window.onload = function () { … } после загрузки страницы задаем обработчики событий для полей и сразу проверяем все поля на валидность. Плюс данного способа в том, что форма остаётся рабочей даже в том случае, если у пользователя отключен JavaScript.
--
Все, конечно лично я тут не все понял т.к. это ново для меня, но то что все работает, это факт. =) и даже без валид скрипта, сам проверил на 0.9.6.3. Делал то что понимал, а это чанки, доки, сниппеты, скрипты, стили ... тест работает.
Проверено: Работает в Evolution 1.0.1 (
пример того, что можно сделать с помощью данного примера)