21.06.2017, 03:40
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
j0hnik, не порите хрени, ID = идентификатор, еще не означает, что нужно именно по нему обращаться к объекту. В данном случае ID, это зло.
Сообщение от ФедорН
|
Правильно ли я понимаю, что я document.querySelector("#id") должен заменить на что-то вроде width=document.querySelector("#form" input[name=width[]]) ?
|
Нет. document.querySelector(selector) вернет первый из набора. Если он один на странице, то все Ок, но если их много, то достучаться до остальных этим методом не получится. И к тому же селектор в данном случае, это строка, которая у вас с ошибкой прописана. Селектор "#form input[name=width[]]" не найдет требуемого, будет получена ошибка о некорректном селекторе, так как квадратные скобки в именах, а также точку необходимо экранировать - "#form input[name=width\\[\\]]" или "#my\\.iden" в случае идентификатора.
Но даже используя корректные селекторы и document.querySelectorAll() все равно не получится, так как элементы добавляются динамически, ранее объявленные обработчики их не затронут. Нужно делегировать обработку родителю form.
$('#form').on('change input', 'select, input', function() {
this.value //здесь, это значение источника, а
this //сам источник, который нужно исключить из набора остальных получаемых элементов
var elm = $(this).closest('.roword').find('select, input').not(this) //набор остальных
})
Можно в набор включить сразу и output, перемножая значения среза элементов 0, -1 и this, помещая результат в последний в наборе (то есть output).
Кроме события change родителю делегируется обработка и события input, так как в поле ввода можно изменять значение не только стрелками, но и непосредственно вводом значения.
Ранее показанный код добавления нужно исправить, забыто об output, кроме того, по уму, поля ввода должны иметь значение по умолчанию 40 (в атрибутах min="40" max="200 и 300").
$('button').click(function() {
$('div.roword').first()
.clone()
.appendTo($('#form'))
.find('select, output').val('')
.end()
.find('input')
.val(40)
});
Но и это еще не все. Если я добавил еще полей, то это еще не означает, что я буду делать в них выбор и отправлять, а значит у пользователя должна быть возможность удаления добавляемых полей.
Последний раз редактировалось laimas, 22.06.2017 в 05:24.
|
|
28.06.2017, 13:33
|
Аспирант
|
|
Регистрация: 19.06.2017
Сообщений: 40
|
|
laimas, спасибо Вам огромное за помощь и развернутые ответы.
По обстоятельствам только вчера добрался, внес правки, но... вообще теперь все не работает пытаюсь разбираться с jQuery теперь
Правильно ли я понимаю, что
window.addEventListener
это теперь
$('#form').on
дополнительно оборачивать в
$(function() {
не требуется?
Последний раз редактировалось ФедорН, 28.06.2017 в 13:37.
|
|
28.06.2017, 13:48
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от ФедорН
|
Правильно ли я понимаю, что
window.addEventListener
это теперь
$('#form').on
|
Нет. $('#form').on, это установка обработчика события в jQuery, и установить его можно только тогда, когда готова DOM, то есть после загрузки документа. Только по наступлению этого события, что и описывается обработчиком события $(function() ... в jQuery, будут доступны объекты документа и можно установить обработчики для них. То есть обязательно
(function() {
$('#form').on(event, function() {
//....
});
})
window.addEventListener установка события в JS, которой и оперирует JQuey (это фреймворк написанный на JS).
Сообщение от ФедорН
|
вообще теперь все не работает
|
Ну если не думать о багах, которые неизбежны в коде вашем, то будет работать.
|
|
28.06.2017, 20:48
|
Аспирант
|
|
Регистрация: 19.06.2017
Сообщений: 40
|
|
Понял
Последний раз редактировалось ФедорН, 28.06.2017 в 21:57.
|
|
28.06.2017, 23:00
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от ФедорН
|
Добавил функцию для учета атрибутов инпутов min и max, в jsfiddle она отлично работает, а у меня в php -нет
|
Что именно на РНР не работает, значения min и max? Ну они и не передаются на сервер.
Что касается сервера, то я могу еще раз повторить - с точки зрения веб приложения, рассчитать на клиенте и результаты расчета отдать серверу, серверу принять и поверить, это профанация.
Грамотно, это так:
1) Опции списка color в значениях должны содержать не величины, которые для расчета, а идентификаторы этих величин.
2) Значения min и мах для полей типа number должен задавать север.
На основании 1 и 2 следует, что параметры всех величин сервер знает, а значит получая идентификатор списка он может проверить истинность выбранного. Выбранные величины ширины/высоты на корректность сервер может проверить, зная величины min и мах.
Вы так не поступаете, что там у вас за проблемы не знаю. Но если вы доверяете все клиенту, то и <output></output> не годится, так как его значение на сервер не передается, даже если задать тегу имя. Тогда уж обычное поле ввода с запретом на ввод.
Говоря о неизбежных багах в коде я имел ввиду min и мах в том числе, но в ином ракурсе.
Сначала о html. Как я говорил, если я добавил набор полей, и даже что-то выбрал в них, то это не означает, что я хочу их отправить, а значит нужна кнопка удаления добавляемых полей в форму.
<div id="form" >
<div class="roword">
<div class="col-md-3 col-sm-6 col-xs-12 form-col-1">
<select form="send" name="color[]">
<option value="">Выберите цвет</option>
<option value="1.2">Зеленый</option>
<option value="1.6">Синий</option>
<option value="1.8">Красный</option>
</select>
</div>
<div class="col-md-3 col-sm-6 col-xs-12 form-col-2">
<input form="send" class="minmax" min="40" max="200" type="number" name="width[]">
</div>
<div class="col-md-3 col-sm-6 col-xs-12 form-col-3">
<input form="send" class="minmax" min="40" max="300" type="number" name="height[]">
</div>
<div class="col-md-3 col-sm-6 col-xs-12 form-col-4">
<output></output> <a style="display:none">Удалить</a>
</div>
</div>
</div>
<div class="clearfix"></div>
<button>Добавить</button>
Код обслуживающий добавление/удаление полей:
$(function() {
$('button').click(function() {
$('div.roword').first() //получаем первый набор полей
.clone() //клонируем его
.appendTo($('#form')) //добавляем набор в форму
.find('select, output').val('') //сбрасываем значения полей
.end() //в начало набора
.find('input') //ищем поле ввода
.val(function() {
return this.min //устанавливаем значение равное минимальному
})
.end() //в начало набора
.find('a').click(function() { //получаем кнопку удаления полей из формы
$(this).closest('.roword').remove() //удаляем добавленное из формы
})
.show() //делаем видимой кнопку удаления
});
});
Проблемы неизбежные заложены в полях типа number. В поле можно вводить значение не только кнопками, но и ручным вводом (утомительно набирать максимальное значение с шагом 1). А то, что это поле типа number совсем не означает, что я не могу ввести в нем "абвгд". Вторая проблема, это "что определяет момент расчета"? Если бы это действие запускалось по кнопке "Рассчитать", тогда проблем с проверкой на min бы не было даже при ручном вводе. Но если расчет запускается при каждом изменении ввода и ввод не кнопками, а ручной, то возникает проблема с определением min. Можно конечно навесить таймер, определяя "вроде бы ввод закончен", но это палка о двух концах. С определением max проблем нет.
//обработка ввода, выбора кнопками и выбора в списке
$('#form').on('change input', 'select, input', function() {
if(this.type == 'number') { //если поле ввода
this.value = this.value.replace(/^0|\D/, ''); //вырезаем не цифровые символы и 0 вначале
if(this.value.length >= this.max.length && this.max < this.value) this.value = this.max //если значение превышает максимальное
}
//расчет
//.........
})
Обработчик определяет - если источник поле number, то удаляет не цифры из набора, сравнивает длину значения и значение с параметрами max. Подобное с min сделать нельзя, так как ввод в поле к примеру 2, еще не означает, что это будет меньше 40, это может быть в итоге 250.
Решить эту проблему можно используя поле не number, а range, тогда необходимость в проверке min/max отпадает (но только для клиента). В этом случае поля описываются так
<input form="send" type="range" min="40" max="300" name="width[]" value="40"> <output>40</output>
и
<input form="send" type="range" min="40" max="200" name="height[]" value="40"> <output>40</output>
В обработчик такой:
$(function() {
$('button').click(function() {
$('div.roword').first() //получаем первый набор полей
.clone() //клонируем его
.appendTo($('#form')) //добавляем набор в форму
.find('select').val('') //сбрасываем значение списка
.end() //в начало набора
.find('input, output') //слайдеры и выводы
.val(function(i) {
return i == 4 ? '' //очищаем output результата расчета
: this.type == 'range' ? this.min //минимальное значение слайдеру
: $(this).prev().attr('min') //отобразить значение слайдера по умолчанию
})
.end() //в начало набора
.find('a').click(function() { //получаем кнопку удаления полей из формы
$(this).closest('.roword').remove() //удаляем добавленное из формы
})
.show() //делаем видимой кнопку удаления
})
//обработка изменения слайдера и выбора в списке
//событие input в данном случае для отображения значения слайдера непосредственно при перемещении ползунка
$('#form').on('change input', 'select, input', function() {
if(this.type == 'range') $(this).next().val(this.value) //отобразить значение слайдера
//расчет
//.........
})
});
|
|
29.06.2017, 14:36
|
Аспирант
|
|
Регистрация: 19.06.2017
Сообщений: 40
|
|
laimas, проблема, упомянутая вчера, из-за которой все не работало, - не подключался jquery.
В итоге подключил только через функцию:
<?php
function my_jquery_scripts() {
wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js');
wp_enqueue_script( 'jquery' );
}
add_action( 'wp_enqueue_scripts', 'my_jquery_scripts' );
?>
через header.php так и не смог подключить ни одним из способов (причина так мне осталась неясна).
За пояснения снова безмерно благодарю.
Фреймворк jQuery мне показался более простым для понимания, но от понимания логики языка пока далек.
Осталось сделать самую малость- расчет.
Но и тут у меня возникли проблемы
Перепробовал много всего, но получил хоть какой-то результат только на этом решении (как понимаю, оно и является одним из/самым простым):
$('#form').on('change input', 'select, input', function() {
if(this.type == 'range') $(this).next().val(this.value)
var h = $('.height').val();
var w = $('.width').val();
var mySelect = $("#form select option:selected").val();
mySelect = (mySelect) ? mySelect : 0; //если ничего не выбрано, правильно?
$('.sum').val(h * w * mySelect);
})
Поле вывода сделал input (с типом text), как вы и посоветовали. Классы инпутам, конечно, присвоил (не буду снова копировать форму), но результат всегда NaN.
Также еще буду думать над тем, чтобы при площади (height * width) равной или менее 2500 добавлялся доп. коэффициент, как это было сделано в первоначальной версии на JS (h <= 2500 && (c *= 1.1); ).
Для меня понятнее, как это делается через if, но есть варианты проще? (только не пишите за меня решение - сам хочу подумать).
Последний раз редактировалось ФедорН, 29.06.2017 в 14:44.
|
|
29.06.2017, 16:39
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от ФедорН
|
через header.php так и не смог подключить ни одним из способов (причина так мне осталась неясна)
|
Если используется CMS, то подключение скриптов в ней производится через конфигурацию. Читайте документацию. То что будет прописываться вне ее в шаблонах может быть переопределено конфигурацией.
Сообщение от ФедорН
|
Фреймворк jQuery мне показался более простым для понимания
|
Это не повод всегда обращаться к его услугам когда доступ уже есть и без него. Например, чтобы меньше бродить по набору в коде добавления элементов, строки кода с 06 по 13 можно заменить этим:
.find('select,input,output') //получаем элементы
.val(function() { //значения по умолчанию
return this.className == 'reset' ? ''
: this.type == 'range'
? this.min
: this.previousSibling.min
})
В данном случае одной функцией производится установка значений по умолчанию всем добавляемым элементам. Для этого списку и полю отображающему результат расчета добавляется класс reset. С учетом того, что элемент хранящий результат расчета заменен на input, его код будет таким:
<input form="send" class="reset" name="result[]" readonly>
Только необходимо обязательное условие - между элементами слайдеров и полями отображающими их значения не должно быть пробелов, любые соседние с ними элементы как угодно. То есть так, например:
<label>Высота:</label>
<input form="send" type="range" min="40" max="200" name="height[]" value="40"><output>40</output>
В противном случае this.previousSibling вернет не input.
Я не выяснял что такое c, не знаю что должно увеличиваться на коэффициент, правьте сами, в примере, это к конечному результату. А расчет, это:
$('#form').on('input', 'select,input', function() {
if(this.type == 'range') $(this).next().val(this.value) //отобразить значение слайдера
//рассчет
var o = $(this).closest('.roword').find('select,input'), //получить все элементы
v = o.eq(0).val(), //значение списка
w = o.eq(1).val(), //ширина
h = o.eq(2).val(), //высота
r = o.last().val(''); //вывод результата, очистить
if(v) { //если в списке выбрано значение
v = v * w * h;
if(w * h <= 2500) v *= 1.1;
r.val(v.toFixed(2))
}
})
Последний раз редактировалось laimas, 29.06.2017 в 17:43.
|
|
03.07.2017, 11:34
|
Аспирант
|
|
Регистрация: 19.06.2017
Сообщений: 40
|
|
laimas, добрый день.
А с какой целью изначально присваивалось ID форме отправки заказа?
Сообщение от laimas
|
Если делать так как я говорил, то <form id="send" class="clearfix callback-form-container" action="{$form_action}" method="post"> - добавляем ID форме.
|
Получается, есть у меня поля калькулятора, добавил я туда значения , получил стоимость, нажимаю на кнопку отправку заказа, которая по
<?php do_action...
вызывает форму.
У всей формы id="send", а у инпутов калькулятора form="send".
Они уже как-то связаны таким образом?
Теперь мне нужно сделать обработчик, который будет вставлять значения (из полей калькулятора) в конкретное поле формы (отправки заказа)?
Последний раз редактировалось ФедорН, 03.07.2017 в 11:43.
|
|
03.07.2017, 11:42
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от ФедорН
|
с какой целью изначально присваивалось ID форме отправки заказа?
|
http://htmlbook.ru/html/input/form
Сама форма у вас где-то в панели потом появляется, а поля калькулятора уже на странице и добавляются. Этот атрибут позволяет просто связать поля вне формы с ней без надобности обработки этого скриптами.
|
|
03.07.2017, 14:52
|
Аспирант
|
|
Регистрация: 19.06.2017
Сообщений: 40
|
|
laimas,
из просмотренных примеров понял, если бы у меня калькулятор был в тегах <form> (но он у меня в div'ах), то форме калькулятора можно было присвоить ID и значения калькулятора могли вставляться, например, в поле textarea формы заказа c атрибутом form="id".
Но у меня получается обратная ситуация - вне тегов form есть инпуты с атрибутом form и форма с id, но которая должна получать значения инпутов, а не отдавать содержимое формы им.
Если же получается так, что в моем случае инпуты уже как бы внутри формы заказа, то их вывести (чтобы видел пользователь) как-то можно в отдельное поле формы заказа?
Извиняюсь, вопрос не относится к JS.
Последний раз редактировалось ФедорН, 03.07.2017 в 15:10.
|
|
|
|