Расчет стоимости услуг на сайте
Один клиент заказал у меня простой скрипт расчета стоимости услуг для своего сайта, попросту говоря калькулятор, складывающий значения выбранных строк в различных списках, а так же значения чекбоксов и радиогрупп. Это очень удобно когда вы вычисляете подходящую стоимость квартиры в Воронеже, запчастей для вашего автомобиля или стоимость всех деталей пластикового окна. Было только одно нестандартное условие: скрипт должен был не только складывать все значения, а универсально рассчитывать результат от поля к полю. Пример: значение поля 1 умножаем на значение поля 2 и затем делим это на значение поля 3. Звучит просто, если заранее знать последовательность, но я её не знал, точнее знал, что последовательность может варьироваться. В итоге родился скрипт, считающий значения полей по формуле (формулам) и позволяющий переключаться с одной формулы на другую. Реализовал я это так:
Вот демо скрипта: Расчет стоимости услуг по формуле.
А вот полный код примера для тех, кому лень скачивать демку.Распространение скрипта разрешено клиентом, так что пользуйтесь =)
- Создаем нужное нам количество полей. Например 3. Присваиваем к каждому полю (или обсчитываемому элементу, коим может быть радио, чекбокс и селекты, как единичные так и мультиплайные) класс 'calculon' чтобы при клике по полю результат каждый раз рассчитывался заново. этого можно и не делать если вы хотите рассчитывать результат исключительно нажатием на кнопку а не realtime. Затем к каждому полю присваиваем уникальный id, к примеру f1, f2, f3.
- В скрипте создаем переменную formula1, которая у нас будет содержать вот такую формулу: '([f1]+[f2])*[f3]' что означает 'сумму первого и второго полей умножить на значение третьего поля'. В квадратных скобках пишутся id полей. В одной формуле может использоваться неограниченное количество одних и тех же полей, а так же дополнительных величин. Пример: '125-([f1]*([f2]-[f1]))/45-[f3]'.
- Далее мы выбираем, какая формула обсчитывается по умолчанию. Для этого в строчке count(***) заменяем звездочки на название нашей переменной с формулой.
- Для того чтобы во время работы страницы поменять формулу расчета - нужно просто ещё раз выполнить count() с нужным названием формулы. Например это можно сделать с помощью кнопки и события onclick.
Вот демо скрипта: Расчет стоимости услуг по формуле.
А вот полный код примера для тех, кому лень скачивать демку.
Code
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Калькулятор</title>
<style>
body{margin:20px;font:11px Tahoma;color:#777;}
div{padding:5px;border:1px solid #ddd;background:#eee;margin:2px;width:400px;}
</style>
</head>
<body>
<div>
Работа с чекбоксом:<br>
<input class='calculon' id='f1' type="checkbox" value="400.55555">
</div>
<div>
Работа с "радио":<br>
<input class='calculon' id='f2' name="Group1" type="radio" value="0">
<input class='calculon' id='f3' name="Group1" type="radio" value="300">
<input class='calculon' id='f4' name="Group1" type="radio" value="500">
</div>
<div>
Работа с многострочным списком:<br>
<select class='calculon' id='f5' size="5" multiple="multiple">
<option value='0'>0</option>
<option value='100'>100</option>
<option value='200'>200</option>
<option value='300'>300</option>
<option value='400'>400</option>
</select>
</div>
<div>
Работа с многострочным списком:<br>
<select class='calculon' id='f6'>
<option value='0'>0</option>
<option value='100'>100</option>
<option value='200'>200</option>
<option value='300'>300</option>
<option value='400'>400</option>
</select>
</div>
<div><input value='считать по формуле 1' type="button" onclick='count(formula1)'><input value='считать по формуле 2' type="button" onclick='count(formula2)'></div>
<div id='calculon'>0</div>
<script type="text/javascript">
if(!Number.prototype.toFixed){
Number.prototype.toFixed=function(e){
var y=Math.round(this*Math.pow(10,e))/Math.pow(10,e);
var i=e-y.toString().length+y.toString().indexOf('.')+1;
if(e>0){
if(y.toString().indexOf('.')<0)return y+'.'+Math.pow(10,e).toString().substring(1);
else if(i>0)return y+Math.pow(10,i).toString().substring(1);
else return y;
}
else return y;
}
}
var formula1 = '[f1]*([f2]+[f3]+[f4])+[f5]-[f6]/10';
var formula2 = '[f1]*([f2]+[f3]+[f4])+[f5]-[f6]/30';
count(formula1);
//Сам скрипт
function count(f){form=f;calculon();}
var elems = document.getElementsByTagName('*');
for(var i=0;i<elems.length;i++){if(/(\^|\b)calculon(\$|\b)/.test(elems[i].className)){
if(elems[i].addEventListener){elems[i].addEventListener('click',calculon,false);}else
if(elems[i].attachEvent){elems[i].attachEvent('onclick',calculon)}
}}
function calculon(){
result=false;
var els = form.match(/\[.+?\]/g);
for(var i=0;i<els.length;i++){
val=0;
var obj = document.getElementById(els[i].match(/\w+/));
if(obj.tagName=='SELECT'){
for(var z=0;z<obj.options.length;z++){
if(!obj.disabled&&obj.options[z].value&&obj.options[z].selected){val=val+parseFloat(obj.options[z].value)}
}
}else{
if(!obj.disabled&&obj.value&&obj.selected||obj.checked){val=val+parseFloat(obj.value)}
}
result = result ? result.replace(els[i],val) : form.replace(els[i],val);
}
document.getElementById('calculon').innerHTML=eval(result).toFixed(2);
}
</script>
</body>
</html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Калькулятор</title>
<style>
body{margin:20px;font:11px Tahoma;color:#777;}
div{padding:5px;border:1px solid #ddd;background:#eee;margin:2px;width:400px;}
</style>
</head>
<body>
<div>
Работа с чекбоксом:<br>
<input class='calculon' id='f1' type="checkbox" value="400.55555">
</div>
<div>
Работа с "радио":<br>
<input class='calculon' id='f2' name="Group1" type="radio" value="0">
<input class='calculon' id='f3' name="Group1" type="radio" value="300">
<input class='calculon' id='f4' name="Group1" type="radio" value="500">
</div>
<div>
Работа с многострочным списком:<br>
<select class='calculon' id='f5' size="5" multiple="multiple">
<option value='0'>0</option>
<option value='100'>100</option>
<option value='200'>200</option>
<option value='300'>300</option>
<option value='400'>400</option>
</select>
</div>
<div>
Работа с многострочным списком:<br>
<select class='calculon' id='f6'>
<option value='0'>0</option>
<option value='100'>100</option>
<option value='200'>200</option>
<option value='300'>300</option>
<option value='400'>400</option>
</select>
</div>
<div><input value='считать по формуле 1' type="button" onclick='count(formula1)'><input value='считать по формуле 2' type="button" onclick='count(formula2)'></div>
<div id='calculon'>0</div>
<script type="text/javascript">
if(!Number.prototype.toFixed){
Number.prototype.toFixed=function(e){
var y=Math.round(this*Math.pow(10,e))/Math.pow(10,e);
var i=e-y.toString().length+y.toString().indexOf('.')+1;
if(e>0){
if(y.toString().indexOf('.')<0)return y+'.'+Math.pow(10,e).toString().substring(1);
else if(i>0)return y+Math.pow(10,i).toString().substring(1);
else return y;
}
else return y;
}
}
var formula1 = '[f1]*([f2]+[f3]+[f4])+[f5]-[f6]/10';
var formula2 = '[f1]*([f2]+[f3]+[f4])+[f5]-[f6]/30';
count(formula1);
//Сам скрипт
function count(f){form=f;calculon();}
var elems = document.getElementsByTagName('*');
for(var i=0;i<elems.length;i++){if(/(\^|\b)calculon(\$|\b)/.test(elems[i].className)){
if(elems[i].addEventListener){elems[i].addEventListener('click',calculon,false);}else
if(elems[i].attachEvent){elems[i].attachEvent('onclick',calculon)}
}}
function calculon(){
result=false;
var els = form.match(/\[.+?\]/g);
for(var i=0;i<els.length;i++){
val=0;
var obj = document.getElementById(els[i].match(/\w+/));
if(obj.tagName=='SELECT'){
for(var z=0;z<obj.options.length;z++){
if(!obj.disabled&&obj.options[z].value&&obj.options[z].selected){val=val+parseFloat(obj.options[z].value)}
}
}else{
if(!obj.disabled&&obj.value&&obj.selected||obj.checked){val=val+parseFloat(obj.value)}
}
result = result ? result.replace(els[i],val) : form.replace(els[i],val);
}
document.getElementById('calculon').innerHTML=eval(result).toFixed(2);
}
</script>
</body>
</html>
15, 9, 9757
Вся замена происходит так:
formula = formula.replace(/\{const:(\w+)\}/ig, function(str,m1){return obj.consts[m1]||0});
for(i in this.cache)
while(formula.indexOf(i)!=-1)
formula = formula.replace(i,this.cache[i].value||this.cache[i].innerHTML||0);
Поля представляют собой обычные input'ы с type="number".