Это третий урок по созданию модуля обратного звонка для Opencart 2. Предыдущие уроки:
Данный урок посвящен отправке данных, которые пользователь будет вводить в форме модального окна.
JS-скрипт для обработки и валидации вводимых данных
Данный скрипт находится в папке catalog / view / javascript
Для начала сделаем обработчик формы:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
$('#xd_zvonok-form').submit(function(event) { event.preventDefault ? event.preventDefault() : (event.returnValue = false); if(!formValidation(event.target)){return false;} var action = $(this).attr('action'); var sendingForm = $(this); var submit_btn = $(this).find('button[type=submit]'); var value_text = $(submit_btn).text(); var waiting_text = 'SENDING'; $.ajax({ type: "POST", url: action, data: $(event.target).serializeArray(), beforeSend:function(){ $(submit_btn).prop( 'disabled', true ); $(submit_btn).addClass('waiting').text(waiting_text); }, success: function(msg,status){ // console.log(msg); var success = true; $(sendingForm).trigger('reset'); $(submit_btn).removeClass('waiting'); $(submit_btn).text(value_text); $(submit_btn).prop( 'disabled', false ); $('#xd_zvonok_modal').modal('hide'); $('#xd_zvonok_modal').on('hidden.bs.modal', function (e) { if (success) { $('#xd_zvonok_success').modal('show'); setTimeout(function(){ console.log('success sending!'); $('#xd_zvonok_success').modal('hide'); }, 4000); success = false; } }); }, error: function(){ $(submit_btn).prop( 'disabled', false ); $(submit_btn).removeClass('waiting').text("ERROR"); setTimeout(function(){ $(submit_btn).delay( 3000 ).text(value_text); }, 3000); } }); event.preventDefault(); }); |
Сначала скрипт отменяет стандартное действие при отправке формы: event.preventDefault ? event.preventDefault() : (event.returnValue = false);
Затем идёт отсылка к функции валидации вводимых данных: if(!formValidation(event.target)){return false;}
Функция валидации проверяет введенные данные и в случае ошибки возвращает false, присваивая класс has-error ошибочным данным:
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 28 29 30 31 32 |
function formValidation(formElem){ var elements = $(formElem).find('.required'); var errorCounter = 0; $(elements).each(function(indx,elem){ var placeholder = $(elem).attr('placeholder'); if($.trim($(elem).val()) == '' || $(elem).val() == placeholder){ $(elem).parent().addClass('has-error'); errorCounter++; } else { $(elem).parent().removeClass('has-error'); } }); $(formElem).find('input[type=tel]').each(function() { var pattern = new RegExp(/^(\(?\+?[0-9]*\)?)?[0-9_\- \(\)]*$/); var data_pattern = $(this).attr('data-pattern'); var data_placeholder = $(this).attr('placeholder'); if (!pattern.test($(this).val()) || $.trim($(this).val()) == '' ) { $('input[name="phone"]').parent().addClass('has-error'); errorCounter++; } else { $(this).parent().removeClass('has-error'); } }); if (errorCounter > 0) { return false; } else { return true; } } |
Валидация простая: проверяет не пустое ли значение у обязательных элементов и не жесткая проверка номера телефона. Маску телефонного номера добавим позднее.
Получив true от функции валидации, js-скрипт, используя Ajax, отправляет данные формы php-обработчику, указанному в атрибуте action самой формы <form id= "xd_zvonok-form" action=«xd_zvonok-send.php» role= "form">
Непосредственно перед отправкой данных js-скрипт блокирует кнопку отправки, чтобы избежать повторных нажатий:
1 2 3 4 |
beforeSend:function(){ $(submit_btn).prop( 'disabled', true ); $(submit_btn).addClass('waiting').text(waiting_text); }, |
Получив ответ от php-скрипта, js-скрипт обрабатывает его и сигнализирует клиенту результат.
Если от php-скрипта пришла ошибка на кнопке отправке появляется надпись ERROR:
1 2 3 4 5 6 7 |
error: function(){ $(submit_btn).prop( 'disabled', false ); $(submit_btn).removeClass('waiting').text("ERROR"); setTimeout(function(){ $(submit_btn).delay( 3000 ).text(value_text); }, 3000); } |
Если от php-скрипта пришел ответ об успешной отправке окно формы исчезает и на 4 секунды всплывает окно об успешной отправке:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
success: function(msg,status){ // console.log(msg); var success = true; $(sendingForm).trigger('reset'); $(submit_btn).removeClass('waiting'); $(submit_btn).text(value_text); $(submit_btn).prop( 'disabled', false ); $('#xd_zvonok_modal').modal('hide'); $('#xd_zvonok_modal').on('hidden.bs.modal', function (e) { if (success) { $('#xd_zvonok_success').modal('show'); setTimeout(function(){ console.log('success sending!'); $('#xd_zvonok_success').modal('hide'); }, 4000); success = false; } }); }, |
Полный листинг js-скрипта xd_zvonok.js
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
$(document).ready(function() { $('#xd_zvonok-form input').focus(function(){ $(this).parent().removeClass('has-error'); }); $('#xd_zvonok-form').submit(function(event) { event.preventDefault ? event.preventDefault() : (event.returnValue = false); if(!formValidation(event.target)){return false;} var action = $(this).attr('action'); var sendingForm = $(this); var submit_btn = $(this).find('button[type=submit]'); var value_text = $(submit_btn).text(); var waiting_text = 'SENDING'; $.ajax({ type: "POST", url: action, data: $(event.target).serializeArray(), beforeSend:function(){ $(submit_btn).prop( 'disabled', true ); $(submit_btn).addClass('waiting').text(waiting_text); }, success: function(msg,status){ // console.log(msg); var success = true; $(sendingForm).trigger('reset'); $(submit_btn).removeClass('waiting'); $(submit_btn).text(value_text); $(submit_btn).prop( 'disabled', false ); $('#xd_zvonok_modal').modal('hide'); $('#xd_zvonok_modal').on('hidden.bs.modal', function (e) { if (success) { $('#xd_zvonok_success').modal('show'); setTimeout(function(){ console.log('success sending!'); $('#xd_zvonok_success').modal('hide'); }, 4000); success = false; } }); }, error: function(){ $(submit_btn).prop( 'disabled', false ); $(submit_btn).removeClass('waiting').text("ERROR"); setTimeout(function(){ $(submit_btn).delay( 3000 ).text(value_text); }, 3000); } }); event.preventDefault(); }); }); function formValidation(formElem){ var elements = $(formElem).find('.required'); var errorCounter = 0; $(elements).each(function(indx,elem){ var placeholder = $(elem).attr('placeholder'); if($.trim($(elem).val()) == '' || $(elem).val() == placeholder){ $(elem).parent().addClass('has-error'); errorCounter++; } else { $(elem).parent().removeClass('has-error'); } }); $(formElem).find('input[type=tel]').each(function() { var pattern = new RegExp(/^(\(?\+?[0-9]*\)?)?[0-9_\- \(\)]*$/); var data_pattern = $(this).attr('data-pattern'); var data_placeholder = $(this).attr('placeholder'); if (!pattern.test($(this).val()) || $.trim($(this).val()) == '' ) { $('input[name="phone"]').parent().addClass('has-error'); errorCounter++; } else { $(this).parent().removeClass('has-error'); } }); if (errorCounter > 0) { return false; } else { return true; } } |
Включим xd_zvonok.js в header.tpl
Для этого внесем изменения в xd_zvonok.ocmod.xml добавив строки:
1 2 3 4 5 6 7 8 9 10 11 12 |
<operation> <search> <![CDATA[ </head> ]]> </search> <add position="before"><![CDATA[ <?php if ($xd_zvonok_status) { ?> <script src="catalog/view/javascript/xd_zvonok.js" type="text/javascript"></script> <?php } ?> ]]></add> </operation> |
Пишем php-обработчик xd_zvonok-send.php
Как обычно, возьмем имеющийся обработчик от модуля упрощенного заказа для Opencart 2 send-order.php и удалим всё "лишнее". Ничего сложного обработчик не представляет: принять данные от js-скрипта, получить данные из настроек, собрать письмо для отправки и отправить его. Листинг файла:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
<?php if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { include "config.php"; // подключаем конфиг /* Осуществляем проверку вводимых данных и их защиту от враждебных скриптов */ $xd_zvonok_title = trim(strip_tags($_POST["xd_zvonok_title"])); $xd_zvonok_name = trim(strip_tags($_POST["xd_zvonok_name"])); $xd_zvonok_name_title = trim(strip_tags($_POST["xd_zvonok_name_title"])); $xd_zvonok_phone = trim(strip_tags($_POST["xd_zvonok_phone"])); $xd_zvonok_phone_title = trim(strip_tags($_POST["xd_zvonok_phone_title"])); $xd_zvonok_message = trim(strip_tags($_POST["xd_zvonok_message"])); $xd_zvonok_message_title = trim(strip_tags($_POST["xd_zvonok_message_title"])); /* Создаем новую переменную, присвоив ей значение */ $message_to_email = "$xd_zvonok_title<br /><br />"; if ($xd_zvonok_name != '') { $message_to_email .= "$xd_zvonok_name_title: $xd_zvonok_name<br />"; } if ($xd_zvonok_phone != '') { $message_to_email .= "$xd_zvonok_phone_title: $xd_zvonok_phone<br />"; } if ($xd_zvonok_message != '') { $message_to_email .= "$xd_zvonok_message_title: $xd_zvonok_message<br />"; } /******************* СОЕДИНЕНИЕ С БАЗОЙ *******************/ $db_host = constant("DB_HOSTNAME"); $db_database = constant("DB_DATABASE"); $db_username = constant("DB_USERNAME"); $db_password = constant("DB_PASSWORD"); $db_prefix = constant("DB_PREFIX"); $db_table = $db_prefix . 'setting'; # Соединение $db_link = mysqli_connect($db_host, $db_username, $db_password, $db_database); $set_charset = mysqli_set_charset($db_link, "utf8"); $result = mysqli_query($db_link, "SELECT * FROM `$db_table` WHERE `code` = 'config'"); while ($row = mysqli_fetch_assoc($result)) { switch ($row['key']) { case 'config_name' : $shop_name = $row['value']; break; } switch ($row['key']) { case 'config_email' : $admin_email = $row['value']; break; } } $shop_name = mb_convert_encoding($shop_name, 'UTF-8', mb_detect_encoding($shop_name)); $admin_email = mb_convert_encoding($admin_email, 'UTF-8', mb_detect_encoding($admin_email)); /* Создаем from email */ $from_email = $shop_name . ' <xd_zvonok@' . $_SERVER['SERVER_NAME'] . '>'; /* Создаем заголовок */ $headers = 'Content-type: text/html; charset=UTF-8' . " \r\n" . 'From:' . $from_email . " \r\n"; //Заголовок для отправки писем без файла /**************** отправка почты *********************/ $subject = "$shop_name: $xd_zvonok_title"; /* Отправляем сообщение, используя mail() функцию */ mail($admin_email, '=?utf-8?B?'.base64_encode($subject).'?=', $message_to_email, $headers); } else { die('spam!'); } |
Тут куча комментариев, так что разобраться не составит труда.
Проверим как работает отправка данных
Теперь мы можем полностью собрать OCMOD архив для установки через "Установку дополнений". Для этого разложим наши файлы по папкам, переименуем xd_zvonok.ocmod.xml в install.xml и соберем всё в архив с именем xd_zvonok.ocmod.zip
Я уже собрал такой архив - скачать его можно здесь на сайте.
Теперь удаляем предыдущие установленные версии модификатора через менеджер дополнений и обновляем модификаторы. Переходим в установку дополнений и пытаемся установить наш zip-архив:
Не забываем обновить модификаторы в менеджере дополнений!
Теперь мы можем вызвать форму в интернет-магазине:
Если всё сработает - Вы должны увидеть окно, свидетельствующее об успешной отправке:
А также должно придти письмо на e-mail адрес администратора:
Модуль работает! В принципе можно остановиться на этом, но можно внести ряд интересных (и не слишком трудных) дополнений и украшательств, которые разберем в следующем уроке "Обратный звонок для Opencart 2. Дополнения и украшательства"