Модальное окно на jQuery с формой отправки письма

Здравствуйте, уважаемые читатели XoZbloga! Однажды я уже писал о модальных окнах, то была статья о создании окон для WordPress с помощью плагина Easy Modal Lite. В этой статье покажу способ создания всплывающего окна на любом сайте. Использовать будем jQuery плагин fancybox. А чтобы добавить смысловой нагрузки статье, вставим в модальное окошко форму отправки письма. Сразу хочу заметить модальные окна на этом плагине работают на всех браузерах. Приступим!


Форма отправки сообщения

Что нам понадобится?! не так уж и много:

  • библиотека jQuery;
  • плагин fancybox;
  • сценарий PHP для отправки сообщения.

Разметка

Скачать актуальную версию плагина Вы сможете по ссылке выше. Что касается плагина fancybox, очень хороший инструмент для создания окон на веб-сайте. В окна можно включать любое содержимое видео, изображения (как по одиночке так и галереей), текст, плавающие фреймы, плагин имеет кучу настроек (о них чуть ниже) + то что он работает одинаково корректно во всех браузерах, очень радует.

Разметку не стану усложнять, просто кликаем по ссылке и открывается окно с формой отправки сообщения:

<a class="modalbox" href="#inline">Отправить сообщение</a>

Где значение атрибута href совпадаем с идентификатором блока div в котором располагается форма отправки письма:

<div id="inline">
   <h2>Отправка сообщения</h2>

   <form id="contact" name="contact" action="#" method="post">
      <label for="email">Ваш E-mail</label>
      <input type="email" id="email" name="email" class="txt">
      <br>
      <label for="msg">Введите сообщение</label>
      <textarea id="msg" name="msg" class="txtarea"></textarea>
     
      <button id="send">Отправить E-mail</button>
   </form>
</div>

Добавим на форму два поля это текст сообщения и электронный адрес отправителя, а также кнопку оправки. После того как пользователь введет e-mail, текст сообщения и нажмет отправить сначала проведем проверку корректности введенной информации затем с помощью ajax запроса отправим данные в PHP сценарий.

Изначально форма скрыта:

#inline { display: none; }

Стили формы

Немного стилей для оформления полей формы и пара классов применяемых к полям при не корректном вводе данных. Когда ошибки исправлены стиль полей становится нормальным.:

.txt {
   display: inline-block;
   color: #676767;
   width: 420px;
   font-family: Arial, Tahoma, sans-serif;
   margin-bottom: 10px;
   border: 1px dotted #ccc;
   padding: 5px 9px;
   font-size: 1.2em;
   line-height: 1.4em;
}

.txtarea {
   display: block;
   resize: none;
   color: #676767;
   font-family: Arial, Tahoma, sans-serif;
   margin-bottom: 10px;
   width: 500px;
   height: 150px;
   border: 1px dotted #ccc;
   padding: 5px 9px;
   font-size: 1.2em;
   line-height: 1.4em;
}

.txt:focus,
.txtarea:focus {
   border-style: solid;
   border-color: #bababa;
   color: #444;
}

input.error,
textarea.error {
   border-color: #973d3d;
   border-style: solid;
   background: #f0bebe;
   color: #a35959;
}

input.error:focus,
textarea.error:focus {
   border-color: #973d3d;
   color: #a35959;
}

Для оформления кнопки «Отправить» будем использовать линейный градиент.:

#send {
   color: #dee5f0;
   display: block;
   cursor: pointer;
   padding: 5px 11px;
   font-size: 1.2em;
   border: solid 1px #224983;
   border-radius: 5px;
   background: #1e4c99;
      background: -webkit-gradient(linear, left top, left bottom, from(#2f52b7), to(#0e3a7d));
         background: -moz-linear-gradient(top, #2f52b7, #0e3a7d);
            background: -webkit-linear-gradient(top, #2f52b7, #0e3a7d);
               background: -o-linear-gradient(top, #2f52b7, #0e3a7d);
                  background: -ms-linear-gradient(top, #2f52b7, #0e3a7d);
                     background: linear-gradient(top, #2f52b7, #0e3a7d);
                        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#2f52b7', endColorstr='#0e3a7d');
}

#send:hover {
   background: #183d80;
      background: -webkit-gradient(linear, left top, left bottom, from(#284f9d), to(#0c2b6b));
         background: -moz-linear-gradient(top,  #284f9d, #0c2b6b);
            background: -webkit-linear-gradient(top, #284f9d, #0c2b6b);
               background: -o-linear-gradient(top, #284f9d, #0c2b6b);
                  background: -ms-linear-gradient(top, #284f9d, #0c2b6b);
                     background: linear-gradient(top, #284f9d, #0c2b6b);
                        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#284f9d', endColorstr='#0c2b6b');
}

#send:active {
   color: #8c9dc0;
      background: -webkit-gradient(linear, left top, left bottom, from(#0e387d), to(#2f55b7));
         background: -moz-linear-gradient(top,  #0e387d,  #2f55b7);
            background: -webkit-linear-gradient(top, #0e387d, #2f55b7);
               background: -o-linear-gradient(top, #0e387d, #2f55b7);
                  background: -ms-linear-gradient(top, #0e387d, #2f55b7);
                     background: linear-gradient(top, #0e387d, #2f55b7);
                        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0e387d', endColorstr='#2f55b7');
}

Fancybox

Переходим к самому интересному, к использованию плагина. Вызываем метод .fancybox в качестве селектора выступает класс ссылки:

$(document).ready(function() {
   $(".modalbox").fancybox();
   $("#contact").submit(function() { return false; });

Также отменяем стандартное действие формы submit (отправить), это позволит нам использовать свой собственный ajax запрос. При вызове метода я не использовал не одного параметра, оставил все значения по умолчанию. Однако о них стоит упомянуть:

Название Описание
padding Отступы до содержимого в окне (По-умолчанию 15px)
margin Расстояние от краев браузера до окна (По-умолчанию 20px)
width Ширина по умолчанию для «IFRAME» и «SWF» содержимого. Кроме того, для «inline», «AJAX» и «HTML» объектов если «AutoSize» устанавливается на «false». Может быть числовым или «Auto». (По-умолчанию 800px)
height Высота по умолчанию для «IFRAME» и «SWF» содержимого. Кроме того, для «inline», «AJAX» и «HTML» объектов если «AutoSize» устанавливается на «false». Может быть числовым или «Auto». (По-умолчанию 600px)
minWidth Минимальная ширина окна (По-умолчанию 100px)
minHeight Минимальная высота окна (По-умолчанию 100px)
maxWidth Максимальная ширина окна (По-умолчанию 9999px)
maxHeight Максимальная высота окна (По-умолчанию 9999px)
autoSize Если «true», то autoHeight и autoWidth также «true» (По-умолчанию true)
autoHeight Если установлен «true», для «inline», «AJAX» и «HTML» содержимого высота определяется автоматически (По-умолчанию false)
autoWidth Если установлен «true», для «inline», «AJAX» и «HTML» содержимого ширина определяется автоматически (По-умолчанию false)
autoResize Если установлено «true», то размер содержимого будет изменяться вместе с изменением окна
autoCenter Если установлено «true», то содержимое будет по центру
fitToView Если установлено «true», то окно будет подстроено под размер браузера перед открытием (По-умолчанию true)
aspectRatio Если установлено «true», то изменение размера ограничено соотношением сторон (По-умолчанию false)
topRatio Вертикальное позиционирование. Если установлено 0.5 то расстояние до верха и низа окна браузера будет одинаково. Если 0 то модальное окно будет сверху (По-умолчанию 0.5)
leftRatio Аналогичный параметр только для горизонтального позиционирования (По-умолчанию 0.5)
scrolling Показывать полосы прокрутки. Может быть установлено ‘auto’, ‘yes’, ‘no’ или ‘visible’ (По-умолчанию auto)
wrapCSS Настраиваемый класс CSS
arrows Если установлено «true», то будут отображаться навигационные кнопки (По-умолчанию true)
closeBtn Если установлено «true», то кнопка закрыть окно будет отображаться (По-умолчанию true)
closeClick Если «true», то при нажатии на содержимое окно закроется (По-умолчанию false)
nextClick Если установлено «true», то в галерее при нажатии на содержимое будет переход к следующей картинке (По-умолчанию false)
mouseWheel Если «true», то галерею можно прокручивать с помощью колесика мыши (По-умолчанию true)
autoPlay Если «true», то при открытии первого элемента галерее начнется слайдшоу (По-умолчанию false)
playSpeed Скорость слайдшоу (По-умолчанию 3000 миллисекунд)
preload Количество картинок миниатюр под основным изображением (По-умолчанию 3)
modal Если «true», навигация и кнопка закрытия будет отключена (По-умолчанию false)
loop Если «true», то в галерее после достижения конца, начнется заново (По-умолчанию true)
ajax Опция для ajax запроса
iframe Опция для управления iframe
swf Опция для управления swf содержимым
keys Можно определить клавиши для навигации по слайдшоу
direction Направление навигации
scrollOutside Если установлено «true», то сценарий будет избегать создания полос прокрутки (По-умолчанию true)
index Переопределяет индекс группы начала (По-умолчанию 0)
type Переопределяет тип содержимого. Поддерживаемые типы «image», «inline», «AJAX», «IFRAME», «SWF» и «HTML» (По-умолчанию null)
href Переопределяет ссылкой источник контента (По-умолчанию null)
content Переопределяет содержимое, которое будет отображаться (По-умолчанию null)
title Переопределяет заголовок, можно установить любой HTML (По-умолчанию null)
tpl Объект, содержащий различные шаблоны
openEffect /
closeEffect /
nextEffect /
prevEffect
Эффект анимации для действий, возможны значения ‘fade’, ‘fade’, ‘elastic’, ‘elastic’
openSpeed /
closeSpeed /
nextSpeed /
prevSpeed
Скорость анимации (По-умолчанию 250)
openEasing /
closeEasing /
nextEasing /
prevEasing
Easing метод для каждого типа перехода (По-умолчанию swing)
openOpacity/
closeOpacity
Если установлено «true», то меняется прозрачность (По-умолчанию true)
openMethod/
closeMethod/
nextMethod/
prevMethod
Эффект transition может принимать значения ‘zoomIn’ / ‘zoomOut’ / ‘changeIn’ / ‘changeOut’
parent Родительский элемент в контейнере. Это полезно для ASP.NET, где верхний элемент является «формой» (По-умолчанию body)

И это еще не все. На странице автора Вы также сможете найти специальные функции для плагина и callback методы, ссылка в начале статьи.

Пользоваться данными параметрами очень просто, допустим мы хотим уменьшить отступы до содержимого контента и высоту содержимого:

$(".modalbox").fancybox({
   padding : 0,
   height : 100
});

Отправка сообщения

Перед отправкой мы будем проверять правильность введенных данных, корректность введенного электронного адреса. Поэтому нам понадобится функция проверки. Использовать будем регулярное выражение:

function validateEmail(email) {
      var reg = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      return reg.test(email);
   }

Последний шаг — это отправка сообщения. Отслеживаем событие клик по кнопке «Отправить»:

$("#send").on("click", function(){
   var emailval  = $("#email").val();
   var msgval    = $("#msg").val();
   var msglen    = msgval.length;
   var mailvalid = validateEmail(emailval);
// Проверка правильности электронного адреса
   if(mailvalid == false) {
      $("#email").addClass("error");
   }
   else if(mailvalid == true){
      $("#email").removeClass("error");
   }
// Проверка длины сообщения
   if(msglen < 4) {
      $("#msg").addClass("error");
   }
   else if(msglen >= 4){
      $("#msg").removeClass("error");
   }

Помещаем в первые две переменные данные, которые ввел пользователь. Определяем длину сообщения (msglen) и проводим проверку введенного электронного адреса (mailvalid). Далее проверяем если в переменная mailvalid равна false, значит электронный адрес введен неверно, и данный инпут будет подсвечен красным. Также проверяем количество введенных символов в текст сообщения, если меньше 4 символов значит показываем, что это ошибка (подсвечиваем текстовый инпут красным).

Теперь о второй части этого обработчика события OnClick нам нужно отправить данные формы в PHP.

if(mailvalid == true && msglen >= 4) {
      // если обе проверки пройдены
      // сначала мы скрываем кнопку отправки
      $("#send").replaceWith("<em>отправка...</em>");

      $.ajax({
         type: 'POST',
         url: 'sendmessage.php',
         data: $("#contact").serialize(),
         success: function(data) {
            if(data == "true") {
               $("#contact").fadeOut("fast", function(){
                  $(this).before("<strong>Успешно! Ваше сообщение отправлено :)</strong>");
                  setTimeout("$.fancybox.close()", 1000);
               });
            }
         }
        });
   }
});

Если оба поля проверены то вместо кнопки «отправить» показываем текст, что происходит отправка сообщения. Это дает пользователю подтверждение того, что оба поля проверены и идет процесс.

Теперь запрос AJAX. Первый параметр запроса это тип передачи данных (POST или GET). Далее указываем файл обработчик (sendmessage.php). Следующий параметр data (данные), методом serialize подготавливаем данные в формах для отправки на сервер.

Если мы получим хороший отклик от сервера (эти данные мы формируем в пхп файле), то мы скроем контактную форму и покажем сообщение об успехе отправки. Я использую SetTimeout(), для того чтобы модальное окно закрылось не сразу а через секунду после отправки данных.

PHP сценарий

Мы посылаем данные, введенные пользователем с помощью JQuery в sendmessage.php. В PHP мы формируем получаем эти данные из POST массива, формируем и отправляем сообщение. Если отправка прошла успешно возвращаем обратно в JQuery true иначе false.

В переменной $sendto мы указываем адрес электронной почты на который будут приходить письма.

$sendto   = "email@mail.ru";
$usermail = $_POST['email'];
$content  = nl2br($_POST['msg']);

// Формирование заголовка письма
$subject  = "Новое сообщение";
$headers  = "From: " . strip_tags($usermail) . "\r\n";
$headers .= "Reply-To: ". strip_tags($usermail) . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html;charset=utf-8 \r\n";

// Формирование тела письма
$msg  = "<html><body style='font-family:Arial,sans-serif;'>";
$msg .= "<h2 style='font-weight:bold;border-bottom:1px dotted #ccc;'>Новое сообщение</h2>\r\n";
$msg .= "<p><strong>От кого:</strong> ".$usermail."</p>\r\n";
$msg .= "<p><strong>Сообщение:</strong> ".$content."</p>\r\n";
$msg .= "</body></html>";

// отправка сообщения
if(@mail($sendto, $subject, $msg, $headers)) {
   echo "true";
} else {
   echo "false";
}


Чтобы оставаться в курсе свежих статей и уроков подписывайтесь на еженедельную почтовую рассылку или на новостную ленту RSS. Спасибо!

  • Kuznetsov Kirill

    Спасибо, очень полезно

  • John

    не работает блеать. 3 часа уже мудохаюсь. Родной index работает, а встраиваю в свой нихера. Все строчки перекопирываю. До этого там уже использовался jqery. может с ним как то конфликтует

    • Да, скорее всего из-за этого. не пробовал использовать jQuery.noConflict() ?

  • Маша

    Супер форма! Установила на свой сайт за 5 мин)

  • Guest

    Всё конечно хорошо но где сменить текст:»Введите адрес электронной почты.» всё излазил не нашел

  • евгений

    Всё конечно хорошо, но где изменить текст ошибки «Введите адрес электронной почты.» излазил все исходники не нашел

    • На счет изменить не знаю, потому-что текст формируется автоматически. Заметьте тип у input поля email, появился в HTML5

    • евгений

      я хотел приспособить ваш скрипт под форму «Обратный звонок». Видно не судьба…Уже нашел другое решение…плохо что неясно — как адаптировать ваш скрипт

    • а в чем не ясность? не подходит тип инпут поля, можно изменить, сам плагин модального окошка адаптируется где угодно…

  • Олександр

    если изменить email в $sendto = «email@mail.ru»; то должно отправить на указанню почту? или еще что-то нужно делать?

  • Николай

    Здравствуйте, плагин отказывается работать с самой свежей версией jquery 1.9,как заставить его работать не подключая старую 1.8 версию(как в данном примере)?

    • Здравствуйте, попробуйте скачать последнюю версию плагина, все прекрасно работает. Ссылка на страницу плагина в самом анонсе статьи.

    • Николай

      Все скачал версию 2.1.4 вроде заработало,спасибо,еще не могли кое что пояснить,вообщем если приглядеться то при открытии модального окна верхняя надпись «модальное окно на jquery» сдвигается вправо пикселей на 20,а при закрытии снова ставиться на свое место,я так понимаю что это связанно с полосой прокрутки справа?что полоса как бы убирается и поэтому обьект сдвигается ближе к правой части браузера,у меня такое происходит с обьектами с позиционированием,не могли бы посказать как решить эту проблемму?

    • попробуйте так:

      body { overflow-y: auto !important; }

      а в стилях для окошка найдите

      .fancybox-lock .fancybox-overlay {
      overflow: auto;
      overflow-y: hidden;
      }

      работает во всех браузерах и в IE 10

    • Николай

      И еще если не сложно не могли бы ответить в теме загрузка изображений с предварительным просмотром,заранее благодарю

    • ок)

  • Владислав

    Не сильно разбираюсь в php. Как правильно добавить дполнительные поля? Телефон, адрес и т.д.?

    • допустим поле телефон, сначала добавляем еще одно поле input с уникальным именем и id на форму:

      Ваш телефон

      потом если необходимо делаем проверку в javascript:

      var tel = $(«#telephone»).val().length;
      if(tel = 6) { $(«#telephone»).removeClass(«error»); }

      и отправляем в PHP:

      if(mailvalid == true && msglen >= 4 && tel >= 6) { …как в уроке…. }

      в php принимаем и встраиваем где надо в тело сообщения:

      $telephone = $_POST[‘telephone’];
      $msg .= «Телефон: «.$telephone.»rn»;

      в последней строчке не забудьте пробелы убрать в тегах и

    • Владислав

      Спасибо большое! Разобрался.

  • Виталий

    Спасибо за хороший урок, и исходники. Добавил ещё 4 поля без валидации. как вы написали в примере (в коментариях). Но при отправке, внизу зависает надпись — «отправка», и окно не сварачивается. И после этого 3 из 4 дописанных мной полей приходят пустыми (как буд-то их не заполняли). подскажите пожалуйста в чем может быть дело?

    • Здравствуйте, не забыли ли Вы принять добавленные поля в PHP? Если нет, проверьте на совпадение значения атрибутов name у полей на форме и названия переменных, которые вы вытаскиваете из массива POST, а также
      $msg .= «Телефон: «.$telephone.»rn»;
      …..
      ……

      должны находится в теле сообщения т.е. внутри

      $msg = «»;
      // Здесь
      $msg .= «»;

      Вы случайно не на локальном сервере работаете?

    • Виталий

      Спасибо за быстрый ответ. Сайт на хостинге «Hostinger». Заметил один нюанс: если добавляю к 2-м существующим полям ещё 1-но, тона почту приходят введённые в форму данные. А если добаваляю ещё 1-но (в сумме 4 выходит), то на последнее поле данные не приходят. Проверил вроде всё правильно. Очень нужна ваша помощь в этом. И ещё раз большое СПАСИБО!

    • Не могли бы Вы ссылку на страницу указать, если что можете через форму отправки письма — кнопка слева

  • Сергей

    Огромное спасибо:) но не могу разобраться — как сделать так, чтобы при нажатии на кнопку (или картинку со ссылкой) вылазило это модальное окно?

    пробовал задавать класс картинке, и даже помещать её в div контейнер с этим классом, не помогло

    • Рад стараться =) Заметьте, значение атрибута href у ссылки совпадает с id блока див с формой, поэтому открыть можно только через ссылку.

      < a class="modalbox" href="#inline"><img src="путь_до_картинки">< /a>
    • Сергей

      тоже вариант) но я сделал по-другому

      когда заработало ОООЧЕНЬ обрадовался:) может кому пригодится