Калькулятор услуг
Здравствуйте!
Нужна помощь с калькулятором. Задача у меня такая: Пытаюсь собрать калькулятор, не могу придумать алгоритм. Цена зависит от таких факторов - размер, тип, упаковка, рамка. Все это уже предусмотренно, и конкретные размеры, тип, пользователю предоставляется только выбор. 1. Начинает пользователь с главного, размер, пусть будет три размера 10*10, 20*20 и 30*30. 2. После выбирает тип, пусть будет тип 1, тип 2 и тип3 Цена зависит от размера т.е. если размер 10*10 и тип1 или тип2 или тип3, то цена 100, если размер 20*20 и тип1 или тип2 или тип3 - цена 200, если размер 30*30 и тип1 или тип 2, или тип3 цена 300. 3. Выбирает рамку, она зависит от размера, если размер 10*10 цена 100, если размер 20*20 цена 200, если 30 на 30 цена 300. Если рамка не нужна, то нечего не складывается. 4. Выбор упаковки, аналогично с рамкой, зависит от размера, 10*10 цена 100, если размер 20*20 цена 200, если 30 на 30 цена 300. Если упаковка не нужна, то нечего не складывается. Т.е. есть 4 пункта, все 4 надо выбрать (кроме последних двух, они не обязательны, но если выбираются, то нужно добавлять к основной сумме). Есть такая форма <form method="POST" action="send.php" id="order"> <label>Размер: </label> <select name="size"> <option></option> </select><br /> <label>Тип: </label> <select name="type"> <option></option> </select><br /> <label>рамка: </label> <select name="ramka"> <option></option> </select><br /> <label>упаковка: </label> <select name="upakovka"> <option></option> </select><br /> <label id="price">Цена: </label><br /> <input type="submit" value="Заказать"> </form> Проверка на заполненность и вычисление цены в зависимости от размера и типа. $("#order").validate({ rules: { size: { required: true }, type: { required: true } ramka: { required: true }, upakovka: { required: true } }, messages: { size: { required: "Не выбран размер." }, type: { required: "Не выбран тип." } ramka: { required: "Не выбрана рамка." }, upakovka: { required: "Не выбрана упаковка." } } }); var sizes = [{ id: 1, value: "А6" }, { id: 2, value: "А5" }, { id: 3, value: "А4" }]; var types = [{ id: 1, value: "Тип 1" }, { id: 2, value: "Тип 2" }, { id: 3, value: "Тип 3" },]; var prices = [ { id: 1, sizeId: 3 && 2 && 1, typeId: 1, value: 0 }, { id: 2, sizeId: 1, typeId: 2, value: 150 }, { id: 3, sizeId: 1, typeId: 3, value: 200 }, { id: 4, sizeId: 2, typeId: 2, value: 250 }, { id: 5, sizeId: 2, typeId: 3, value: 300 }, { id: 6, sizeId: 3, typeId: 2, value: 350 }, { id: 7, sizeId: 3, typeId: 3, value: 400 }, ]; var sizeEl = $("#order")[0]["size"], typeEl = $("#order")[0]["type"]; for (var i = 0; i < sizes.length; i++) sizeEl.add(new Option(sizes[i].value, sizes[i].id)); for (var i = 0; i < types.length; i++) typeEl.add(new Option(types[i].value, types[i].id)); sizeEl.onchange = calculatePrice; typeEl.onchange = calculatePrice; function calculatePrice() { var e = prices.find(function (e) { return e.sizeId == sizeEl.value && e.typeId == typeEl.value; }); $("#price").text("Цена: " + (e ? e.value : "")); } Запутался как дальше реализовать сложение следующих двух пунктов. Понимаю что аналогично с размером, но как правильно - не могу понять. |
Начинает пользователь с главного, размер, пусть будет три размера 10*10, 20*20 и 30*30.
<select name="size">.... Логично. После выбирает тип, пусть будет тип 1, тип 2 и тип3. <select name="type">... Логично. Выбирает рамку, она зависит от размера <select name="ramka">... Не понятно. Размера чего, основного или своего? Если первое, то причем тут список? А упаковка, это черная, белая, красная или просто выбрать/нет ее? |
Цитата:
Есть изделие, оно основное, и все относится к изделию, размер изделия, упаковка и рамка для изделия, рамка и упаковка зависит от размера самого изделия, больше изделие нужно больше упаковки, и больше рамка, а значит выше себестоимость. Рамка пусть будет рамка1, рамка 2, рамка3. Упаковка пусть будет упаковка1, упаковка2, упаковка3. Т.е. выбирает пользователь размер, например 10*10 и например тип2, получает цену, к ней нужно добавить цену рамки и упаковки, если они нужны (на выбор пользователя), а их цены зависят от размеров изделия (10*10 и т.д.). По итогу пользователь получает конечную сумму изделия, с учетом выбранного размера, а также включенную в стоимость рамку и упаковку если это нужно. |
Я о том, что в описанном не понять как же все завязано на размере. Было бы понятно, например, если бы:
1) Есть базовая цена Р печати за площадь рваную 1 дм (10х10). Выбор площади, это умножение базовой цены на выбранную площадь. 2) Есть базовые цены за рамку из: дерева, пластика, железа. В зависимости от площади печати (размера исходника) базовая цена каждого типа рамки увеличивается на N%: 10х10 = Р * 1, 20х20 = Р * 1.2, 30х30 = Р * 1.3. Подобным образом и цены других позиций зависят от размера. 3) Упаковка, либо выбрать ее и добавить к цене фиксированное значение и это флажок, либо это разный материал упаковки с разной ценой или также надбавка за размер только тогда это список. Либо вариант для всех один - выбор любого в позициях, это увеличение единственной базовой цены на N%. У вас же фиксированные цены для каждой позиции в каждом списке, но при этом запутанный объект их описывающий. |
Давайте попробую по другому объяснить.
1. Вот базовые цены: ![]() 2. Рамки ![]() 3. Упаковка ![]() Пользователь выбирает размер и тип обязательно (получает цену из пункта 1), затем (необязательно), выбирает рамку (цена рамки складывается с базовой ценой), после (необязательно), выбирает упаковку (цена упаковки складывается с предыдущей ценой). Т.е. основной пункт это размеры, размеры фиксированные, тип, упаковка, рамка - у каждого пункта своя цена и зависит от этого самого размера, и складывается между собой. |
Если так, то зачем же кухня с объектом, поместите цены в опции списков, а по изменению в них выбирайте значения списков (либо из data атрибута выбранной опции) и складывайте. Что может быть проще?
|
Цитата:
|
Ну кроме указанного в таблице есть ведь список, главный, где нужно выбрать размер, так?
|
Цитата:
1. Выбор размера (10*10, 20*20, 30*30). 2. Тип - цена зависит от пункта 1. Цены только из таблицы с типами. 3. Рамка - цена зависит от пункта 1. Цены только из таблицы с рамками. 4. Упаковка - цена зависит от пункта 1. Цены только из таблицы с упаковками. Алгоритм пользователя: Выбор размера - 10*10 Выбор типа - тип 2 Цена = 150 Выбор рамки (необязательно) - Рамка2 Цена = 150 + 150 Цена = 300 Выбор упаковки (необязательно) - Зеленая Цена 300 + 200 Цена: 500 ![]() |
Я на JQ, чтобы короче:
<form method="POST" action="send.php" id="order"> <label>Размер: </label> <select name="size" required> <option value="" disabled selected>Выбрать</option> <option value="1">10x10</option> <option value="2">20x20</option> <option value="3">30x30</option> </select><br /> <label>Тип: </label> <select name="type" required> <option value="" disabled selected>Выбрать</option> <option data-price="[100,200,300]" value="1">Тип 1</option> <option data-price="[150,250,350]" value="2">Тип 2</option> <option data-price="[200,300,400]" value="3">Тип 3</option> </select><br /> <label>рамка: </label> <select name="frame"> <option value="">Выбрать</option> <option data-price="[100,200,300]" value="1">Рамка 1</option> <option data-price="[150,250,350]" value="2">Рамка 2</option> <option data-price="[200,300,400]" value="3">Рамка 3</option> </select><br /> <label>упаковка: </label> <select name="packing"> <option value="">Выбрать</option> <option data-price="[100,200,300]" value="1">Красная</option> <option data-price="[150,250,350]" value="2">Синяя</option> <option data-price="[200,300,400]" value="3">Зеленая</option> </select><br /> Итого: <output name="total"></output><br /> <input type="submit" value="Заказать"> </form> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $('#order').on('change', 'select', function(e) { var f = e.delegateTarget, p = $('select', f), size = p.eq(0).children(':selected').index()-1, v = 0; if(!p.filter(function() { return this.required && !this.value }).length) { $.each(p.slice(1), function() { v += this.value ? $(this).children(':selected').data('price')[size] : 0 }); f.total.value = v; } }); </script> Правильно считает? |
Нет :-? Размер 30*30, тип3, выходит 400, рамка 2, должно получится 750, калькулятор считает 700.
|
Цитата:
Размер 30*30 - это индекс 2. Далее по вашим ценам: Для типа 3 это значение из массива: [300,350,400][2] = 400. Для рамки 2 это значение из массива: [200,250,300][2] = 300. 400 + 300 = 700 |
А, да, надо было цены из таблицы вставлять в массивы не построчно, а брать из столбцов. Ну это не проблема, сейчас исправим.
|
Берм размер 20*20, тип 3, цена 300, рамку 2, цена 550, а калькулятор выводит 500.
|
А ок :)
|
Исправлено, теперь верно?
|
Вроде как да :) Спасибо. Еще такой момент остался, если пользователь не выбрал рамку или упаковку, как отобразить текущую цену?
|
Цитата:
|
Если нужно чтобы расчет производился в любом случае, то убрать условие и так:
$('#order').on('change', 'select', function(e) { var f = e.delegateTarget, p = $('select', f), v = 0, size = p.eq(0).val()-1; $.each(p.slice(1), function() { v += this.value ? $(this).children(':selected').data('price')[size] : 0 }); f.total.value = v; }); |
Цитата:
Цитата:
Цитата:
|
А ну вот. Да. Теперь все работает. Еще потестирую. Проще было чем в варианте из шапки темы)
Спасибо! |
Цитата:
С условием проверки будет считать при обязательном выборе размера и типа (код менять не требуется), а без условия всегда (код как в посте #19). |
Цитата:
Но если вы оперируете списками, от которых зависит итог, значит имена первичных ключей (свойств) объекта выгоднее сделать равными именам списков, под которыми содержатся обычные индексные массивы цен. Зачем тут объекты, если проще представлять размер как индекс этих массивов? |
Цитата:
|
Цитата:
size = p.eq(0).val()-1; то есть, берется значение списка размера (выбранной опции), вычитается 1, понятно, потому как индексы начинаются с 0. Но ведь форма отправляется на сервер, а значения опций списков это только в примере чинно от 1, а в реалии это может быть какое-то уникальное значение, например 83, под которым сервер хранит такой набор. Непорядок, и корректнее брать индекс выбранной опции (опции списка, это коллекция, следовательно в этом наборе они тоже имеют индексы) минус единица: size = p.eq(0).children(':selected').index()-1 |
Часовой пояс GMT +3, время: 02:01. |