Один скрипт для всех форм на странице
Доброго времени суток! Прошу профессиональной помощи у всех сведущих в js людей. Я только недавно стал изучать js программирование и недавно столкнулся с весьма неприятной задачей. Неделя активного гуглежа и раздумий не к чему меня не привели, по этому искренне надеюсь найти помощь здесь.
Дело вот в чем, у меня есть контактная форма на сайте, для нее я написал скрипт валидации и отправки через ajax, вот собственно разметка формы и сам скрипт: <form method="post" action="main_c/order" id="contact-form"> <input type="text" name="name" placeholder="Имя *" /> <input type="text" name="phone" placeholder="Телефона *" /> <button type="submit" name="btn_order_1" id="btn_1">Жду звонка!</button> </form> <div id="thank-you" class="display"> <p>Спасибо за заявку! <small>Наш дежурный инженер свяжется с Вами в ближайшее время</small></p> </div> <script> $(function(){ var contact_form = $("#contact-form"); var input = $("#contact-form input"); var name = $("#contact-form input[name='name']"); var phone = $("#contact-form input[name='phone']"); contact_form.find("[name=btn_order_1]").click(function(event){ event.preventDefault(); event.stopPropagation(); if(name.val() == "", phone.val() == ""){ //error console.log('false'); input.addClass('input-error'); return false; }else{ //true console.log('true'); input.removeClass('input-error'); input.addClass('input-success'); contact_form.ajaxSubmit({ url: contact_form.attr('action'), type: contact_form.attr('method') || 'POST', data: { btn_order_1: 1, }, dataType: 'json', success: function(data) { contact_form.find('[type=reset]').click(); }, }); setTimeout(function(){ $('#thank-you').fadeIn(300); $('#contact-form').fadeOut(300); },300); } return false; }); }); </script> И все бы хорошо, все работает так как я и хочу, НО как быть если форм у меня несколько, скажем штук 20. Выходит что мне нужно этот скрипт копировать 20 раз и проставлять в нем и в самих формах новые уникальные id - это как то жутко неудобно а самое главное не правильно. Подскажите пожалуйста что именно мне нужно изменить/дописать в алгоритм этого скрипта что бы он работал как и работает но сразу для всех форм на сайте (само собой имеется в виду только активная форма, с которой в данный момент контактирует пользователь). |
Цитата:
$("form").submit(function(event){ //значения полей формы для проверки this.name.value this.phone.value //и т.д. "form" может быть селектором по имени класса, который объявляется проверяемым формам. |
Уважаемый laimas. Благодарю за корректировки относительно моих переменных. И прошу прощения за некую не компетентность, как я и писал выше, я только начинаю изучать js и не совсем понимаю Ваш ответ, не могли бы Вы объяснить немного подробнее?
|
Цитата:
1) Выбрасывайте из формы все ID, они совсем не нужны, кроме, если неким полям требуется индивидуальный дополнительный сценарий, тогда может еще это и потребоваться. В данном же случае надобности в них нет. 2) Обрабатывайте событие onsubmit форм (в jQuery события указываются без предшествующего on). this в этом обработчике ссылается на DOM элемент источник события, в данном случае форма, которая отправляется. Если на странице только формы, которые нужно обработать этим единым сценарием, то в качестве селектора можно прописать и $('form'), в противном случае можно задать этим формам одно имя класса, например ".callform" и установить на них обработчик $('.callform'). Значение любого поля формы, это ссылка на текущую форму -> имя поля формы -> его значение, то есть this.phone.value. 3) Трудно представить 20 идентичных форм на странице, но уж если надо, и их обрабатывает один скрипт, а серверу нужно знать с какой части страницы отправка, то этим идентификатором для сервера может служить кнопка отправки формы, если ее оформить так: <button type="submit" name="btn_order" value="1">Жду звонка!</button> и значение value="1" у каждой формы свое, то по этому значению ключа btn_order сервер может определять место отправки. 4) Если 20 форм, а данные ими передаваемые различны, то таким образом не получится проверка данных, нужно описывать правила проверки, чтобы одним сценарием их проверять. JQuery по русски, почитайте. |
Добрый вечер! Я внес в скрипт все Ваши рекомендации, вот что у меня получилось:
<form method="post" action="main_c/order_1"> <input type="text" name="name" placeholder="Введите ваше имя *" /><br /> <input type="text" name="phone" placeholder="Введите номер телефона *" /><br /> <button type="submit" name="btn_order">Жду звонка!</button> </form> <script> $(document).ready(function () { $("form").submit(function(event){ event.preventDefault(); event.stopPropagation(); if(this.name.value() == "", this.phone.value() == ""){ //error console.log('false'); return false; }else{ //true console.log('true'); $("form").ajaxSubmit({ url: $("form").attr('action'), type: $("form").attr('method') || 'POST', data: { btn_order: 1, }, dataType: 'json', success: function(data) { $("form").find('[type=reset]').click(); }, }); } return false; }); }) <script> Но скрипт не работает, происходит ошибка Uncaught TypeError: this.name.value is not a function, я как только не колдовал сегодня с этим this.name.value, ошибка постоянно одна и та же. Подскажите пожалуйста что моя неопытная голова делает не так? |
if(this.name.value == "" || this.phone.value == ""){ value - это свойство, а не функция. Но в данном случае такая проверка некорректна так как значение " " пройдет такую проверку, а не является верным. Лучше так, используя тот же JQ if(!$.trim(this.name.value) || !$.trim(this.phone.value)) { |
Уважаемый laimas, снова Вас благодарю за помощь, сейчас все заработало! Но снова приношу извинения за свою непроглядную тупость)
Скрипт сейчас имеет вид: $(document).ready(function () { $("form").submit(function(event){ event.preventDefault(); if(!$.trim(this.name.value) || !$.trim(this.phone_1.value)){ //error console.log('false'); $("input").addClass('input-error'); return false; }else{ //true console.log('true'); $("input").removeClass('input-error'); $("input").addClass('input-success'); $("form").ajaxSubmit({ url: $("form").attr('action'), type: $("form").attr('method') || 'POST', dataType: 'json', success: function(data) { $("form").find('[type=reset]').click(); }, }); } return false; }); }) Но все равно продолжает воздействовать на все формы на странице... Что со мной все таки не так?) |
event.preventDefault(); - отменяет действие формы по умолчанию, то есть ее отправление, а значит
$("input").addClass('input-error'); return false; - это уже в общем то пустой звук, как и в конце обработчика return false; ни к чему. Если .ajaxSubmit(), значит у вас CMS MODX, так? Или подключили этот плагин? Вкупе с jQuery каша полнейшая. console.log(вывод) - это для отладки, проверили, выбросили. $("input").removeClass('input-error'); и $("input").addClass('input-success'); - это кому, если форм на странице 20 штук, а обработчик отправки формы работает с текущей? И если их 20, то это что:$("form").attr('action'), $("form").find('[type=reset]').click(), а обработчик отправки формы работает с текущей? Либо вы не просто копируете то, что вам пишут, но еще и читаете и вникаете что к чему, либо вы напишите монстра, который естественно работать не будет. Словами это так: $("form").submit(function(event) { - всем формам на странице установить ЭТОТ обработчик события отправления формы event.preventDefault(); - отменить отправку формы по умолчанию а далее в обработчике this - это ссылка на текущую форму (но не как объект jQuery, а как DOM элемент страницы), и достаточно использовать ее а не ковыряться опять в структуре DOM. Но в дальнейшем, по ходу сценария this может быть и переопределен, а также посредством JQ изменяются классы элементов, тогда можно поступить так, с учетом того, что в jQuery своих ajax-методов как грязи и .ajaxSubmit() совсем не нужен: $.valHooks.input = { //тут мы будем обрезать крайние пробелы у полей формы, перед использованием их значений посредством jQuery get: function(e) { return $.trim(e.value) } }; $(function() { //тоже самое что и $(document).ready(function ()... $('form').submit(function(e) { e.preventDefault(); var f = this, //текущая! форма как DOM, а не объект jQuery e = $(f.elements).slice(0, -2), //а это элементы формы без кнопки submit/reset, если они последние форме!, как объекты jQuery //и если 20 форм имеют разнличные поля, и какждая из них может иметь разное их количество, //то все проверки нужно делать проходом в цикле по этим полям, проверяя значения каждого err = 0; //признак ошибки проверки полей формы - если 0, то нет, 1 - есть незаполненные поля e.each(function() { //проверяем значение поля, и если не заполнено, //то err = 1 и добавляем класс input-error элементу }) //проверяем, если нет ошибок отправляем форму if(!err) { $.ajax({ //отправка формы ajax-методом url: f.action, type: 'POST', dataType: 'json', success: function(data) { f.reset(); //сбрасываем текущую форму! }, }) } }); }); Что у вас за 20 форм, почему не обрабатываются только богу известно, и коли хотите получить ответ, то приводите примеры форм, либо поясняйте в чем их разница/схожесть. |
Добрый день, laimas! Я понимаю что уже порядком надоел Вам свой некомпетентностью, но увы, не знаю как по другому научиться делать правильно, и очень благодарен Вам за то что Вы уже очень помогли!
Сегодня новый день и возникли новые вопросы. Я переделал свой скрипт, учитывая все Ваши правки (некоторые моменты написал по другому, в силу того что не совсем понял что вы имели в виду в предыдущем ответе). Самое главное что теперь скрипт заработал так как нужно, каждая форма обрабатывается им отдельно, и я необычайно этому рад) Но появилась другая проблема которая поставила меня в тупик окончательно, перестала работать отправка формы. То есть сам скрипт отлично отрабатывает все условия и генерирует отправку. НО сама отправка не происходит - данные в БД не заносятся, и на e-mail соответственно не отправляются. Могли бы Вы еще разок взглянуть на все мое "творение" в комплексе? <!-- Форма --> <form method="post" action="main_c/order_1"> <input type="text" name="name" placeholder="Введите ваше имя *" /><br /> <input type="text" name="phone_1" placeholder="Введите номер телефона *" /><br /> <button type="submit" name="btn_order_1">Жду звонка!</button> </form> <!-- EXIT Форма --> <!-- Скрипт --> $(function() { $.valHooks.input = { get: function(e) { return $.trim(e.value) } }; $("form").submit(function(e){ e.preventDefault(); var f = this, e = $(f.elements).slice(0, -1); if(!$.trim(this.name.value) || !$.trim(this.phone_1.value) || !$.trim(this.email.value)){ e.addClass('input-error'); }else{ e.removeClass('input-error'); e.addClass('input-success'); $.ajax({ url: f.action, type: 'POST', dataType: 'json', success: function(data) { f.reset(); }, }); } }); }) <!-- EXIT Скрипт --> <!-- Контролер который обрабатывает форму и генерирует отправку на email --> function order_1() { if (isset($_POST['btn_order_1'])) { header("Cache-Control: no-store, no-cache, must-revalidate"); $client['name'] = $_POST['name']; $client['phone_1'] = $_POST['phone_1']; $this->main_model->new_order_1($client); $this->email->from('ru.marketroll@gmail.com', 'ЗАГОЛОВОК'); $this->email->to('velichko.my.site@gmail.com'); $this->email->subject('ТЕМА'); $this->email->message('Имя: '.$client['name']."\r\n".'Номер телефона: '.$client['phone_1']); $this->email->send(); echo json_encode($client); } } <!-- EXIT Контролер --> <!-- Модель которая принимает данные от контролера и вносит их в БД --> function new_order_1($client){ $array = array( 'name' => $client['name'], 'phone_1' => $client['phone_1'] ); $this->db->insert('client', $array); } <!-- EXIT Модель --> Самое главное что вся эта система работала с тем изначальным (пусть и очень корявым/страшным) скриптом, а сейчас нет, и консоль не дает не каких ошибок, просто нечего не происходит. Я понимаю что причина этого кроется где-то здесь, в алгоритме отправки через AJAX: $.ajax({ url: f.action, type: 'POST', dataType: 'json', success: function(data) { f.reset(); }, }); Но в чем именно причина, до меня не как не доходит, перепробовал все что мог и все что знал... |
Я задаю вопросы, на которые нет ответа, и что ответить?
Что за куча форм, они все на 100% идентичные как приведенная, то есть имеют одинаковое количество полей и самое главное одни и те же имена их? |
Вопрос даже не в количестве форм, 20 - это я написал утрировано. Их несколько (всего 4) просто они находятся в разных местах и имею разный дизайн. Они передают имя, телефон и заголовок. Заголовок подтягивается не из инпутов, а не посредственно из верстки. Значения "name" у всех однотипных инпутов - одинаковые.
На самом деле (как по мне) эта информация уже бесполезна, потому как с предыдущей задачей Вы помогли мне успешно справиться, хотя Вам разумеется виднее. Теперь мне просто нужно устранить возникшую ошибку с отправкой. |
Цитата:
if(!$.trim(this.name.value) || !$.trim(this.phone_1.value) || !$.trim(this.email.value)) проверить любую форму с полями имеющими какие угодно имена? Вы утрируете задавая вопрос, а отвечающий вам что должен догадываться об этом, сам додуматься, что у вас на самом деле? Если формы идентичные, имена полей одинаковы, это одно, иначе скрипт будет иной. Что метод $.ajax() jQuery, что плагин ajaxSubmit, это одно и тоже - организация асинхронного обмена данными с сервером. Что первый, что второй можно и выбросить, и написать такой обмен на том, что эти методы и используют - XMLHTTPRequest. И без проблем данные будут отправляться серверу, то есть ошибка совсем не в методе. Смотрим то, что вы считаете "бесполезной информацией": <input type="text" name="name" placeholder="Введите ваше имя *" /><br /> <input type="text" name="phone_1" placeholder="Введите номер телефона *" /><br /> А скрипт проверяет условия: if(!$.trim(this.name.value) || !$.trim(this.phone_1.value) || !$.trim(this.email.value)) Вопрос - если в форме отсутствует как таковое поле email будет ли выполнятся условие и в конечном итоге отправка формы серверу? e = $(f.elements).slice(0, -1); - я пояснял почему так взяты элементы формы, и что их нужно будет проверить проходом в цикле. Как выясняется все одинаково, можно обойтись и без цикла, но e.addClass('input-error'); - добавит указанный класс всем элементам формы содержащимся в коллекции е. Но ведь не факт, что все поля не заполнены, может не заполнено только одно, а зачем все отмечать ошибкой? По поводу приема данных сервером. Это в общем то бардак, а не прием данных. Северу все равно проверялись ли данные на клиенте ли нет, он просто обязан проверить их - заполнены ли поля обязательные, возможно и имя, если есть на него условия, а уж номер телефона и электронного адреса (что-то его не видно не только на клиенте, но и в обработке на сервере) тем более нужно проверять. Иначе вы получите на сервере набор мусора, типа name=>" " и phone_1=>abc. header("Cache-Control: no-store, no-cache, must-revalidate"); - это для чего? А это зачем - echo json_encode($client);? Зачем отправлять данные клиенту, которые он получил, а клиент их и так имеет, тем более, судя по коду, клиенту они и не нужны. Вот эта функция вообще прелесть: function new_order_1($client){ $array = array( 'name' => $client['name'], 'phone_1' => $client['phone_1'] ); $this->db->insert('client', $array); } То есть переменная $client уже определена массивом array( 'name' = $_POST['name']; 'phone_1' = $_POST['phone_1']; ); в функции order_1(), передана в функцию, а значит достаточно в ней - $this->db->insert('client', $client); и все, нет надо массив переписать заново только под другим именем, чтобы записать в базу. Это даже не глупость, это дикость. :) А если данные сервер не проверяет к тому же, представляете что может база хранить? Заголовок подтягивается не из инпутов, а не посредственно из верстки. - этого в коде не наблюдается, а догадаться чего там у вас конкретно, как я уже говорил, я не могу. Будет конкретика, будет и конкретный код без лишнего. |
Я приношу извинения за некоторые неточности, предыдущие сообщение писал не с ПК а с телефона, по этому не много запутался что и от куда копирую.
На счет наличия пункта "email" - давайте его упустим, добавить одно поле, в процессе я смогу и сам, надеюсь справлюсь:) Оставим в сценарии проверки: Цитата:
Цитата:
Цитата:
Если сформулировать это все конкретно и на конкретном примере: - Я создал только что тестовую страницу, в ней есть 2 формы (абсолютно идентичны между собой): <form method="post" action="main_c/order_1"> <input type="text" name="name" placeholder="Введите ваше имя *" /><br /> <input type="text" name="phone_1" placeholder="Введите номер телефона *" /><br /> <button type="submit" name="btn_order_1">Жду звонка!</button> </form> <form method="post" action="main_c/order_1"> <input type="text" name="name" placeholder="Введите ваше имя *" /><br /> <input type="text" name="phone_1" placeholder="Введите номер телефона *" /><br /> <button type="submit" name="btn_order_1">Жду звонка!</button> </form> Они должны обрабатываться вот этим скриптом: $(function() { $.valHooks.input = { get: function(e) { return $.trim(e.value) } }; $("form").submit(function(e){ e.preventDefault(); var f = this, e = $(f.elements).slice(0, -1); if(!$.trim(this.name.value) || !$.trim(this.phone_1.value) || !$.trim(this.email.value)){ e.addClass('input-error'); }else{ e.removeClass('input-error'); e.addClass('input-success'); $.ajax({ url: f.action, type: 'POST', dataType: 'json', success: function(data) { f.reset(); }, }); } }); }) И передаваться на сервер, где полученную информацию с формы обрабатывает вот этот контролер: function order_1() { if (isset($_POST['btn_order_1'])) { $client['name'] = $_POST['name']; $client['phone_1'] = $_POST['phone_1']; $this->main_model->new_order_1($client); $this->email->from('ru.marketroll@gmail.com', 'ЗАГОЛОВОК'); $this->email->to('velichko.my.site@gmail.com'); $this->email->subject('ТЕМА'); $this->email->message('Имя: '.$client['name']."\r\n".'Номер телефона: '.$client['phone_1']); $this->email->send(); echo json_encode($client); } Повторюсь, я знаю что обработчик на сервере написан "не красиво", - я это обязательно исправлю, но чуть позже. Сейчас для меня главное что он работает. А вот при передаче ему информации от клиента происходит какая то ерунда, с которой я увы не могу сам разобраться. Я постарался изложить всю конкретику которую только смог собрать. Если нужны еще какие либо подробности, или исходные данные, пожалуйста уточните что именно это может быть |
Цитата:
А чтобы сервер принимал данные, их нужно отправлять (копировал код и сам проглядел): $(function() { $("form").submit(function(e){ e.preventDefault(); var f = this, //получает элементы формы без кнопки submit и которые не заполнены e = $(f.elements).slice(0, -1).removeClass('input-error').filter(function() { return !$.trim(this.value) }); //если есть незаполненные поля, то пометить их if(e.length) e.addClass('input-error'); //иначе отправка формы else { e.addClass('input-success'); $.ajax({ url: f.action, type: 'POST', data: $(f).serialize(), //отправляемые данные, если надо добавить что-то производное, то $(f).serialize()+'&key_name='+значение dataType: 'json', success: function(data) { //data содержит ответ сервера, и если сервер вернет ошибки заполнения формы, то сообщить //и только если север подтвердит, что все ОК, только тогда сброс формы f.reset(); } }); } }); }); |
Спасибо Вам огромное! Все заработало! Заработало еще лучше чем я мог ожидать. Еще раз спасибо, за помощь и потраченное время
|
Если ожидать лучшего, хотя данная проверка, это минимум, и с таковой браузеры умные уже сами справляются. А вот чего не должен ожидать сервер, так это множество отправлений одной формы. Отправление формы не обязательно быстрый процесс, даже на стадии подключения к серверу могут быть задержки, а клиент может не дождавшись ответа сервера отправить форму вновь. Поэтому как минимальное на стороне клиента нужно блокировать отправление формы на время обмена данными с сервером. Для этого строки 4-8 кода можно переписать так:
var f = this, s = $(f.elements).last(), e = s.end().slice(0, -1).removeClass('input-error').filter(function() { return !$.trim(this.value) }); перед строкой 13 добавить: s.prop('disabled', 1);, а в success: function(data) добавить: s.prop('disabled', 0); Строку 13 переписать так: s.end().not(s).addClass('input-success'); |
Одним словом laimas в прошлый раз не понял смысла атрибутов pattern, required и всех остальных.
|
Цитата:
Бабушку свою учу, чмо. |
Часовой пояс GMT +3, время: 18:30. |