j0hnik, не порите хрени, ID = идентификатор, еще не означает, что нужно именно по нему обращаться к объекту. В данном случае ID, это зло.
Цитата:
Но даже используя корректные селекторы и 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, спасибо Вам огромное за помощь и развернутые ответы.
По обстоятельствам только вчера добрался, внес правки, но... вообще теперь все не работает :) пытаюсь разбираться с jQuery теперь Правильно ли я понимаю, что window.addEventListener это теперь $('#form').on дополнительно оборачивать в $(function() {не требуется? |
Цитата:
(function() { $('#form').on(event, function() { //.... }); }) window.addEventListener установка события в JS, которой и оперирует JQuey (это фреймворк написанный на JS). Цитата:
|
Понял :)
|
Цитата:
Что касается сервера, то я могу еще раз повторить - с точки зрения веб приложения, рассчитать на клиенте и результаты расчета отдать серверу, серверу принять и поверить, это профанация. Грамотно, это так: 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) //отобразить значение слайдера //расчет //......... }) }); |
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, но есть варианты проще? (только не пишите за меня решение - сам хочу подумать). |
Цитата:
Цитата:
.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, добрый день.
А с какой целью изначально присваивалось ID форме отправки заказа? Цитата:
<?php do_action... вызывает форму. У всей формы id="send", а у инпутов калькулятора form="send". Они уже как-то связаны таким образом? Теперь мне нужно сделать обработчик, который будет вставлять значения (из полей калькулятора) в конкретное поле формы (отправки заказа)? |
Цитата:
Сама форма у вас где-то в панели потом появляется, а поля калькулятора уже на странице и добавляются. Этот атрибут позволяет просто связать поля вне формы с ней без надобности обработки этого скриптами. |
laimas,
из просмотренных примеров понял, если бы у меня калькулятор был в тегах <form> (но он у меня в div'ах), то форме калькулятора можно было присвоить ID и значения калькулятора могли вставляться, например, в поле textarea формы заказа c атрибутом form="id". Но у меня получается обратная ситуация - вне тегов form есть инпуты с атрибутом form и форма с id, но которая должна получать значения инпутов, а не отдавать содержимое формы им. Если же получается так, что в моем случае инпуты уже как бы внутри формы заказа, то их вывести (чтобы видел пользователь) как-то можно в отдельное поле формы заказа? Извиняюсь, вопрос не относится к JS. |
Цитата:
Цитата:
<form id="as" onsubmit="alert(JSON.stringify([].map.call(this.elements, function(e) { return e.name + '=' + e.value }))); return false"> <button name="sender" value="1">GO</button> </form> <input form="as" name="n1" value="2" /> <input form="as" name="n2" value="3" /> |
Получается, пользователь не видит уже свой заказ, когда открывается форма заказа и атрибут form вставить данные (input values из div) в одно из полей формы возможности не дает.
Тогда, как понимаю, можно сделать функцию, где создать массив .map с данными из div_roword input Преобразовать их в текст: return $(elem).text(); и вывести в поле teaxarea в форме заказа, присвоив ему id="orderItems": $("#orderItems").text(arr); |
Цитата:
Вы либо огород городите, либо .... Я уже говорил, так как вы принимаете заказы от клиента, это мягко говоря действовать "через попу". :) Но если уж так поступать, то элементам полей калькулятора не нужны даже и имена, связывать их с какой-то формой вообще не нужно, так как отправлять их на сервер то зачем? Ну появилась у вас форма, что там в нее ввели типа личных данных, и в ней же есть teaxarea, в которую по событию отправки формы, получая выбранные значение и расчеты из полей калькулятора, и помещайте их. Это и отправляйте на сервер, если вас это удовлетворяет. |
Цитата:
Цитата:
Правильно ли я написал, что нужна функция? |
Цитата:
|
laimas, добавил функцию в плагин, все работает, но немного не так.
$(function () { var orderInfo = ''; $(".roword input, .roword select").each(function() { orderInfo += ' x ' + this.value; }); $("#orderItems").html(orderInfo); }); А именно, необходимо вывести ни value select, а наименование выбранной опции (в моем случае цвет). Не могу найти, как сделать. Попытки реализовать через что-то типа select.attr(), input.attr() успехом не увенчались - все перестает работать. И еще одна проблема. Если пользователь заполняет одну строку калькулятора, то она вставляется с помощью вышеприведенной функции в поле textarea формы заказа, а если пользователь добавил несколько строк, то всегда добавляется минус одна, по какой-то причине удаляется последняя строка. При вызове попап-формы заказа прямо видно, как последняя срока исчезает. Не подскажите, где копать. |
Цитата:
if(this.tagName=='SELECT') $(this).text() это и будет текст выбранной опции. К тому же тогда нужны тексты и для других значений, а если так паковать в строку, то в textarea все будет в одну строку. Лучше var orderInfo = []; и помещая в этот массив одну строку из калькулятора, в textarea записать массив как orderInfo.join('\n'). |
Цитата:
$(function () { var orderInfo = []; $(".roword select, .roword input").map(function() { if(this.tagName=='SELECT') orderInfo += $(this).find('option:selected').text(); else orderInfo += ' | ' + this.value; }); $("#orderItems").html(orderInfo); }); пытался сделать по-разному, но это единственный рабочий вариант. Вы сказали, что всю (одну) строку брать из калькулятора в массив, как понял, это: $(".roword").map(function() результат нулевой. также у меня не работает orderInfo.join('\n') как понимаю я, если записывать в textarea, то это должно быть: $("#orderItems").html(orderInfo.join('\n')); Возможно, не работает из-за некорректной реализации массива. |
Цитата:
Вам действительно так все пофигу и что там придет от клиента не важно? Наверное же надо добавлять в вывод только тогда, когда пользователем что-то выбрано. Я показывал код, в котором расчет будет только тогда, когда выбрано все необходимое. А значит проверяя значение поля результата расчета, можно решать нужно ли добавлять. Следовательно проверив не пуст ли массив orderInfo, можно будет решать нужна ли отправка формы вообще, или же...? Бог с ним, пусть будет некая доля пофигизма, но не настолько же. :) $(function () { ... это готовность DOM, если ваш код выполняется значит форма присутствует на странице, она просто не отображается. Поэтому это не добавление "кода в плагин" как вы писали. Переделать это нужно. Лучше так - в обработчике вызывающем эту форму и формировать информацию о заказе, и заблокировав отправку формы (если конечно пофигизм не 100%), снимая блокировку если orderInfo не пуст. Что там за кнопка вызывает форму я не в курсе, ищите, разбирайтесь, а помещение информацию в форму, это: var orderInfo = $.map($('.roword'), function(e) { var o = $(e).find('select,input'); //получить все элементы if(o.eq(3).val()) return o.eq(0).children(':selected').text() + ' ' + o.eq(1).val() + 'x' + o.eq(2).val() + ' ' + o.eq(3).val() //если был выбор }); if(orderInfo.length) $('textarea').val(orderInfo.join('\n')) |
laimas, благодарю, все работает. Почему удалялась последняя строка калькулятора, о чем упоминал ранее, тоже разобрался, исправил.
Насчет пофигизма... конечно же, мне не все равно, я обычно разбираюсь в вещах и делаю, как положено. Но случай с программированием - совсем другое - его нельзя освоить за день, неделю, месяц... Тут уже решает приоритет. Протестировать актуальность продукта важнее, чем сделать очень корректный сайт, потратив время, поняв, что он никому не нужен. Если есть посещаемость, то косяки можно отслеживать через вебвизор и допиливать что-то. Над тем, что пользователь в калькулятор может ввести не все данные, мой код все равно сработает, я просто не задумался. На данный момент я просто не способен отличить самодеятельность от реализации (по крайней мере, когда я пытаюсь что-то писать сам) в виду отсутствия теоретических и практических знаний. По запросу решения одной задачи находится много примеров в гугле, которые пишутся также людьми с разным уровнем знаний и опыта. И если некоторый код я еще хоть как-то начал разбирать и понимать, то насколько он профессионально написан, увы, нет. Быть откровенным - изначально я пришел сюда, чтобы решить вышеописанные задачи и сильно не заморачиваться. Но вы так интересно все поясняете, что вчера взялся читать "Выразительный JavaScript". Есть желание разобраться, но нужно подкреплять теорию именно задачами реальными, которые нужны тебе. Лично понял для себя это так. Мне, новичку, сложно провести корреляцию между задачей "Шахматная доска" и тем, где и в какой реальной ситуации это может пригодиться. На реальной же практике все яснее. У меня и раньше были вялые попытки освоить язык, теперь я понял, как проще можно это делать. |
Цитата:
Цитата:
Я не думаю, что вы напрочь лишены и образного, и логического мышления, и вам никогда не решить простую житейскую задачу. Ваш подъезд навещает разносчик пиццы предлагая ее от фирмы работающей под слоганом "Мы предугадываем ваши желания!". 1) Я не заказывал, а мне принесли, должен ли я быть осторожным? 2) Действительно ли в коробках пицца или все что угодно? 3) Если я возьму предложенное, должен ли я оплатить не проверяя что в коробках? Решение этой задачи потребует от вас знаний Javascript? Нет конечно. Но ведь и в вашей задаче, которая из жизни переложена в виртуальность все тот же разносчик пиццы. В вашем случае разносчик пиццы - это Интернет. Коробки с пиццей - это форма. Понимая сущность реального "пицционера", прекрасно понимаем, что и виртуальный не обязательно ангел и его коробки всегда наполнены, и наполнены нужным для нас. А значит сценарий вашего приложения обязательно должен иметь условие - я принимаю пиццу (форму) только тогда, когда она в коробке. Разве до этого момента нужны знания конкретного языка программирования? Нет. 1) Предлагаем выбрать цвет и размеры. Надо ли вести расчет если что-то из этого не выбрано? Нет. 2) Надо ли помещать из предложенного в форму если не было расчетов? Нет. 3) Отправлять ли форму если поле заказа не заполнено? Нет. Конкретизируя детально эти три постулата получаем еще вопросы, и находим на них ответы: 2а) Нужно очищать поле заказа формы перед помещением в него результатов выбора? а) если не очищаем, придется разбираться в каждой строке заказа (которые уже есть в форме) - она действительна или же пользователь от этого набора отказался. б) если очищаем, то поле всегда будет иметь только реальные на текущий момент записи заказа. Значит выбираем б). Даже и намека на какой либо оператор языка нет в этом. А вот как это сделать на каком либо языке, вот тут да, нужны уже его знания. Но ведь мы уже имеем конкретный план действий, а значит можем целенаправленно вести поиск нужного среди инструментов этого языка. Не имея стратегического плана, врага не победить. ;) Цитата:
Веб приложение, это системный блок на сервере, монитор и терминал на клиенте. Если ваше веб приложение, это запрос клиента -> ответ сервера "Привет мир!", то вопросов нет к серверному языку (сценарию) принимающему этот запрос. Но если терминал клиента не просто для ввода, но и для передачи данных от клиента, то это кардинально меняет ситуацию. Ваше приложение не просто принимает данные от терминала клиента, а использует для передачи этих данных конечному потребителю очень больное и чувствительное для любого хоста - порт 25. Отдавая на откуп клиенту использование этого порта по любому поводу, вы нарушаете принципы безопасности. Когда мы перестали убивать мамонтов и появился Интернет, он был в зачаточном состоянии. Тогда, только отвыкнув от мамонтов, мы воспринимали его как диковинку, и электронные письма в нем "Привет Мери! Приходи к пещере у Большого камня." могли быть лишь слегка дерзкими для юной Мери. Но с тех пор все изменилось, электронная почта теперь не так безобидна и она может быть не только спамом, но и оружием, и порт 25 не только как почтовое отделение, но и местом целенаправленных атак. Разносчик пиццы всегда за дверью и он никуда не денется, всегда будет стоять за вашими дверями. И если в своей квартире вы отвечаете только за себя, то в квартире арендованной (хосте) вы несете ответственность и за ее мебель, и оборудование предоставленное вам в аренду. |
Если мои предки ловили бабочек, от этого не были изгоями, были сытыми и счастливыми, не охотясь на мамонтов (или через раз-другой), то я в этом не вижу ничего плохого. Даже наоборот, т.к. их было меньшинствО, кто умел так существовать. Я склонен к оптимистичным сценариям :)
Мышление у Программистов отличается, бесспорно. Это только положительная сторона. Да, столь глубоко я в задачу не погружался. Со светлой головой не пытался в нее вникнуть и разобрать. У вас это (я бы сказал, творческий процесс) происходит на автомате. Это ваше. Но на уровне "если... то...", как мне кажется, я довольно хорошо понимаю задачи, если разбираю, но вот как дело доходит до языка... Я до недавнего времени был перфекционистом, последнее время стараюсь уходить от этого. Еще год-полтора назад я бы не просто согласился с вашей точкой зрения по дилетантству, но и принял бы ее с большой вероятностью. Но когда у человека нет знаний, чтобы сделать правильно, и возможности, чтобы тебе это сделал профессионал, то остается 2 варианта: сделать и попробовать, как можешь, или ничего не делать. По-моему, второй вариант более страшен. Очень много вещей в мире создается с дилетантским подходом, даже уже в изученных сферах. В каких-то случаях цена ошибки -даже жизнь. Поэтому, как уже говорил, это мнение верно с точки зрения конкретной специализации. Да и в любой сфере опытный специалист предостережет. В т.ч. на то и нужны знания и опыт :) А ошибки- они неизбежны всегда и везде. Флуд разводить не хочется, да и в такой дискуссии истина не родится :) |
laimas, добрый день. посмею обратиться еще раз :)
При тестировании калькулятора обнаружились проблемы в ie 10, 11 и некоторых мобильных браузерах,а именно: 1. При изменении значение ползунка, не меняется значение output, value всегда остается начальным. В связи с этим, а также неудобством использования ползунка (точный поиск значения с шагом 1) на мобильных устройствах, хотелось бы реализовать рядом с ползунком iput text или number, который будет дублировать значение ползунка,а при вводе числа в input будет меняться значение ползунка, учитывая ограничения, и их автоматическая корректировка, max и min. Пересмотрел примеры, но везде это реализовано через ui, к которому прибегать не хотелось бы (оставив input range). Попытки "колхоза" результата не дали вообще никакого :) 2. При вводе значений, результат в поле input readonly не выводится. Он может вывестись/измениться, только в том случае если вы установите курсор в это поле, нажмете клавишу на клавиатуре. В противном случае поле всегда статично. не подскажете, в чем причина? 3. не совсем вопрос по теме, но в некоторых случаях также не отображается "направляющая" ползунка, а только передвигающая часть (бегунок). стилизовал с учетом кроссбраузерности, но так и не могу понять, в чем причина. возможно, скажете, где копать? Чтобы не искать код, дублирую: $(function() { $('button.addMore').click(function() { $('div.roword').first() .clone() .appendTo($('#form')) .find('select').val('') .end() .find('divinput') .val(function(i) { return i == 4 ? '' : this.type == 'range' ? this.min : $(this).prev().attr('min') }) .end() .find('a').click(function() { $(this).closest('.roword').remove() }) .show() }) $('#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 <= 2399) v *= 1.1 else if(w * h >= 2400 && w * h <= 3999) v *= 1.055 else if(w * h >= 4000 && w * h <= 5399) v *= 1.03; else if(w * h >= 5400 && w * h <= 6399) v *= 1.0135; r.val(v.toFixed(0)) } }) }); var orderInfo = $.map($('.roword'), function(e) { //вставляет значения из калькулятора в форму заказа var o = $(e).find('select,input'); //получить все элементы if(o.eq(3).val()) return o.eq(0).children(':selected').text() + ' ' + o.eq(1).val() + 'x' + o.eq(2).val() + ' ' + o.eq(3).val() //если был выбор }); if(orderInfo.length) $('textarea#orderItems').val(orderInfo.join('\n')) <div id="form" > <div class="roword"> <div class="col-md-3 col-sm-6 col-xs-12 form-col-1"> <select form="send" name="type[]"> <option value="">Выберите цвет</option> <option value="1.1">Зеленый</option> <option value="1.4">Синий</option> <option value="1.75">Красный</option> </select> </div> <div class="col-md-3 col-sm-6 col-xs-12 form-col-2"> <input form="send" type="range" min="40" max="200" name="height[]" value="40"> </div> <div class="col-md-3 col-sm-6 col-xs-12 form-col-3"> <input form="send" type="range" min="40" max="300" name="width[]" value="40"> <output>40</output> </div> <div class="col-md-2 col-sm-5 col-xs-10 form-col-4"> <input class="myPrice" form="send" type="text" name="result[]"> </div> <div class="col-md-1 col-sm-1 col-xs-2 form-col-5"> <a style="display:none" class="close"></a> </div> <div class="clearfix"></div> </div> </div> <div class="clearfix addbutton"></div> <button class="addMore">Добавить еще</button> |
Цитата:
Так что если требуется поддержка старых браузеров, мобильных устройств различных, то от новшеств HTML5 придется отказаться. Для того чтобы иметь ползунок на всех устройствах и пишут свое, при этом не обязательно UI нужен, плагинов реализующих ползунок много, ищите в сети, читайте о поддержке его браузерами, выбирайте. А чтобы данный базовый код сделать рабочим под всеми устройствами, это уже тема не для рамок форума вопрос/ответ. Цитата:
Цитата:
|
Понял, благодарю. Да, пожалуй, это я упустил момент с html5.
Тогда если можно, только прояснить момент с тем, что не работает автоматический расчет. Не работает в ie 10, ie 11. И в firefox прежних версий стоимость не обновляется сразу, пока не сдвинешь бегунок. Т.е. вы выбрали все параметры, получили стоимость, потом меняете цвет на более дорогой, но если бегунок не трогали, то стоимость останется от более дешевого цвета, такой попадет в форму заказа. Цитата:
$(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() //делаем видимой кнопку удаления }); }); поле вывода результата <input class="myPrice" form="send" type="text" name="result[]" readonly> Правда, тогда может и логично, если ie не знаком с range, то он и не может считать результат - просто не поминает, что такое value из range. |
Нет, IE11 поддерживает range, но событие input для всех нет. А вот элемент output IE не поддерживает. Можно заменить output на span, а обработчик расчета дополнить событием change, то есть вот так будут выглядеть его первые строки теперь:
$('#form').on('input change', 'select,input', function() { if(this.type == 'range') $(this).next().text(this.value) //отобразить значение слайдера (теперь это span) //код далее Судя по этому class="col-md-3 col-sm-6 col-xs-12 form-col-1" используется бутсрап, это значит учитывается и мобильные устройства, а в нем есть все свое, включая и плагин range. PS. О проблеме с readonly так и не понял. |
Цитата:
Цитата:
А вот ситуацию с output, который выводит значение input range это не изменило, даже наоборот. Я добавил change, заменил <output>40</output> на <span>40</span>, даже в последней версии chrome данное значение перестало работать - всегда (при изменении положения ползунка) отображается минимальный value, т.е. 40. |
Цитата:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(function() { $('button').click(function() { $('div.roword').first() .clone() .appendTo($('#form')) .find('select').val('') .end() .find('input, output') .val(function(i) { return i == 4 ? '' : this.type == 'range' ? this.min : $(this).prev().attr('min') }) .end() .find('a').click(function() { $(this).closest('.roword').remove() }) .show() }) //обработка изменения слайдера и выбора в списке $('#form').on('input change', 'select,input', function() { if(this.type == 'range') $(this).next().text(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 <= 2399) v *= 1.1 else if(w * h >= 2400 && w * h <= 3999) v *= 1.055 else if(w * h >= 4000 && w * h <= 5399) v *= 1.03; else if(w * h >= 5400 && w * h <= 6399) v *= 1.0135; r.val(v.toFixed()) } }) }); </script> </head> <body> <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" type="range" min="40" max="300" name="width[]" value="40"><span>40</span> </div> <div class="col-md-3 col-sm-6 col-xs-12 form-col-3"> <input form="send" type="range" min="40" max="200" name="height[]" value="40"><span>40</span> </div> <div class="col-md-3 col-sm-6 col-xs-12 form-col-4"> <input class="myPrice" form="send" type="text" name="result[]" readonly> <a style="display:none">Удалить</a> </div> </div> </div> <div class="clearfix"></div> <button>Добавить</button> </body> </html> |
ФедорН,
забыл, в расчетах под span изменил, а в клонировании нет, должно быть так: $('button').click(function() { $('div.roword').first() .clone() .appendTo($('#form')) .find('select,[type=text]').val('') .end() .find('input') .val(function() { return this.min }) .end() .find('span').text(function() { return $(this).prev()[0].min }) .end() .find('a').click(function() { $(this).closest('.roword').remove() }) .show() }); |
laimas, действительно, это у меня была ошибка в коде скрипта.
Все работает. Спасибо. Можно еще вопрос. Каждой строке списка товаров в форме заказа хотелось бы в начале присвоить номер. var orderInfo = $.map($('.roword'), function(e) { //вставляет значения из калькулятора в форму заказа var i = $(".roword"), u = +i.val(); var o = $(e).find('select,input'); //получить все элементы if(o.eq(3).val()) return u+'.' + ' ' + o.eq(0).children(':selected').text() + ' ' + o.eq(1).val() + 'x' + o.eq(2).val() + ' ' + o.eq(3).val() //если был выбор }); if(orderInfo.length) $('textarea#orderItems').val(orderInfo.join('\n')) Насколько удалось накопать, самый понятный вариант - когда мы присваиваем номер каждому div .roword. Добавилvar i = $(".roword"), u = +i.val(); и возврат значения u в строке , но нумерация строк начинается с нуля, при попытке добавить счетчик или начать с .val(+1) получаю NaN. Почему значение получается не числовое? Как понимаю, вначале я привожу как раз u к числовому значению. |
Зачем номер и для чего?
|
Цитата:
У меня получается так, что на странице клиент может добавить в калькулятор несколько позиций, далее открывает форму заказа и эти позиции, каждая в виде отдельной строки, добавляются в поле textarea. Высота textarea ограничена, прокрутка не сильно удобна, при просмотре позиций (особенно если несколько одинаковых) легко сбиться. Я смотрел, как сделать поле textarea "резиновым" (скрипт впечатляющий). Также "примерял" div contenteditable, не впечатлил (и оформить корректно его мне не удалось). Поэтому я решил остановиться на том, чтобы просто пронумеровать строки, так по цифрам сбиться будет невозможно. |
Цитата:
Если уж так охота пронумеровать в итоге, то есть в textarea, то методы $.map, $each и прочие, первым аргументом в функцию передают индекс элемента. Добавляйте к нему 1, получите нумерацию от 1 до ... |
Цитата:
|
Более полезным было бы удалять из набора не выбранные опции, а так как фактически это задается выбором в списке, то те, в которых нет выбора в нем. Делать это нужно по вызову формы
$('div.roword').filter(function() { return !$(this).find('select').val() }).remove(); А нумерация чисто для красоты, вряд ли пользователь будет запоминать под каким номером он чего-то набрал, да и так ли это важно. |
Цитата:
Я сначала ее в калькулятор запихал, естественно, первая строка при загрузке сразу удалялась :) потом уже в форму заказа добавил, все ок. но как понял, теоретически, если реализовать как-то через .onclick, то возможно было и в калькулятор добавить? (это сугубо для понимания. код не нужен). Цитата:
Грубо на примере: ![]() Заказали вы 10 Полей с исходным текстом, по высоте texarea весь список не отображается (максимум видно 2 позиции за раз), нужно пролистывать стрелками прокрутки. Пересчитать таким образом, что их 10, будет довольно проблематично, учитывая, что все они одинаковы. А так они пронумерованы, вы сразу видите: 1. Поле с исходным текстом ... 10. Поле с исходным текстом Это и всего лишь имелось в виду. |
Цитата:
$('div.roword').not(':first').filter(function() { return !$(this).find('select').val() }) .remove() .end() Это коллекция, в которой все после первого набора заполнены. Заполнено ли все в первой неизвестно, требуется проверка. |
Цитата:
|
Цитата:
Поле можно добавлять используя ранее заготовленный шаблон, который описан в переменной или хранится как данные в атрибуте кнопки Добавить: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style> .myPrice { border: none; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(function() { $('button').click(function() { $($(this).data('ins')).appendTo($('#form')) .find('.myPrice').focus(function() { this.blur() }) .end() .find('a').click(function() { $(this).closest('.roword').remove() }) }); //обработка изменения слайдера и выбора в списке $('#form').on('input change', 'select,input', function() { if(this.type == 'range') $(this).next().text(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 <= 2399) v *= 1.1 else if(w * h >= 2400 && w * h <= 3999) v *= 1.055 else if(w * h >= 4000 && w * h <= 5399) v *= 1.03; else if(w * h >= 5400 && w * h <= 6399) v *= 1.0135; r.val(v.toFixed()) } }); $('a').click(function() { $('div.roword').filter(function() { return !$(this).find('select').val() }).remove(); var res = $.map($('div.roword'), function(e, i) { return i+1 + '. ' + $.map($(e).find('select,input'), function(e) { return e.value }).join(', '); }).join('\n'); if(res) { $('textarea').val(res); $('button').prop('disabled', 0); } }) }); </script> </head> <body> <div id="form"></div> <div class="clearfix"></div> <button data-ins='<div class="roword"><div class="col-md-3 col-sm-6 col-xs-12 form-col-1"><select> <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 type="range" min="40" max="300" value="40"><span>40</span></div> <div class="col-md-3 col-sm-6 col-xs-12 form-col-3"><input type="range" min="40" max="200" value="40"><span>40</span></div> <div class="col-md-3 col-sm-6 col-xs-12 form-col-4"><input class="myPrice" type="text" readonly> <a>Удалить</a></div></div>'>Добавить</button> <div><textarea></textarea></div> <a>Send</a> </body> </html> |
laimas, прошу прощения, только сейчас увидел ваше последнее сообщение. Вы имели в виду, что первая строка требует проверки перед тем, как добавить следующую или же перед тем, как перейти к форме заказа?
Но что-то в коде не так: перестали работать калькулятор и кнопка "добавить", с первой же строки калькулятора появилась не кликабельная "удалить". В html были несколько ошибок (видимо, образовались в процессе копирования): съехал <button data-ins=' и <div class="clearfix"></div>, и как понимаю, это лишний кусок: <div><textarea></textarea></div> <a>Send</a> Это я поправил. Но скрипт не могу. |
Часовой пояс GMT +3, время: 04:19. |