Сообщение от MC-XOBAHCK
|
остальные виды смогу теперь сам добавить
|
Несомненно. Это в качестве коды - теперь будем считать как и ранее предполагалось, делая перерасчет и при смене единиц измерения через триггер. В коде выше он был убран потому, что расчет производился бы только для первой группы и плюс возникали бы некоторые ошибки.
Как работает расчет для группы понятно, теперь мы просто изменим обращение к группе - не по классу текущего поля, а будем циклом обходить их родительские контейнеры. А для того чтобы было удобнее их идентифицировать, индикатором родителя будет не имя класса, а атрибут. Для первой комнаты это будет:
<div class="row plos" data-area="rectangle">
для второй
<div class="row plos" data-area="triangle">
Остальной html-код остается без изменения.
Код обработчиков практически тот же самый, только изменим селекторы полей, ну и циклом обход родителей. Как ранее предлагалось, массив описывающий единицы измерения заменен массивом объектов, в которых описаны единицы измерения, символ квадрата, значений после запятой, множитель. Значения кнопок выбора служат индексами этого массива.
Добавим расчет пирамиды Хеопса, у которой основания смежных сторон может быть не равно, что с добавлением расчета площади основания даст более трех площадей для расчета и вывода. Все это ради показать, что первое задается функцией calculate для соответствующей группы, а второе, количеством элементов вывода и возвращаемым функцией calculate массиве рассчитанных площадей. Основной код при этом не будет изменяться, добавляются только html-элементы группы и расчет для нее в функции calculate.
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
function calculate(group, values) {
var a, b;
switch(group) {
case 'rectangle': a = values[0] * values[1], b = values[2] * values[3];
return [a, b, a && b ? (a + b) * 2 : 0];
break;
case 'triangle': a = values[0] * values[1] * .5, b = (values[2] + values[3]) * values[4] * .5;
return [a, b, a && b ? (a + b) * 2 : 0];
break;
case 'pyramid': a = values[0] * values[1] * .5, b = values[0] * values[2] * .5;
return [a, b, values[1] * values[2], a && b ? (a + b) * 2 : 0];
}
}
$(function() {
var dim = [{unt: 'м', sqr: '²', dec: 2, mul: .001}, {unt: 'мм', sqr: '²', dec: 0, mul: 1000}],
side = $('input:text')
.on('keyup', function() {
this.value = this.value.replace(/[,\.]+/,'.').replace(/[^\d.]/,'');
var u = unit.filter(':checked').val();
//расчет площадей для всех заполненных полей
$('[data-area]').each(function() {
//группу определяет атрибут data-area
var group = $(this).data('area'),
values = $.map(side.filter('.'+group), function(e) {
var v = parseFloat(e.value);
return v || 0
}),
area = calculate(group, values);
$(this).find('.area').each(function(i, e) {
$(e).text(
area[i] ? area[i].toFixed(dim[u].dec) + ' ' + dim[u].unt + dim[u].sqr : ''
)
})
})
}),
unit = $('input:radio')
.change(function() {
var u = this.value;
$('.unit').text(dim[u].unt);
side.val(function() {
var v = parseFloat(this.value);
if(v) return (v * dim[u].mul).toFixed(dim[u].dec)
}).trigger('keyup');
});
});
</script>
</head>
<body>
<label><input type="radio" name="unit" value="0" checked="" /> метры</label>
<label><input type="radio" name="unit" value="1" /> миллиметры</label>
<h3>Пирамида</h3>
<p>Стены треугольные. Противоположные стены равны</p>
<div class="row plos" data-area="pyramid">
<div class="col-sm-6">
<h4>Треугольная стена</h4>
<div class="st1">Высота стен: </div>
<div class="st2"><input class="pyramid" /> <span class="unit">м</span></div>
<div class="st1">Длина основания первой стены: </div>
<div class="st2"><input class="pyramid" /> <span class="unit">м</span></div>
<div class="st1">Длина основания второй стены: </div>
<div class="st2"><input class="pyramid" /> <span class="unit">м</span></div>
</div>
<div class="col-sm-6">
Площадь 1 стены: <span class="area"></span><br>
Площадь 2 стены: <span class="area"></span><br>
Площадь основания: <span class="area"></span><br>
Площадь всех стен: <span class="area"></span>
</div>
</div>
</body>
</html>
По мере добавления различных расчетов станет ясно, что функция calculate, это в общем то диспетчер-сборщик и расчеты площадей однотипных фигур выгоднее поместить в функции, если они могут быть в различных комнатах. Диспетчер знает к какой из них обратиться и в каком порядке помещать расчеты в возвращаемый массив.
До этого момента в формулах расчета площадей не встречалось деления. Если таковое будет, то надо помнить о делении на ноль. В языках программирования такая ситуация возвращает ошибку, кроме Javascript, который возвращает Infinity. Хрен их знает этих разработчиков JS при чем тут бесконечность, процессоров с бесконечной разрядностью в ближайшем тысячелетии точно не будет. А с точки зрения архитектора бесконечные размеры стен точно беспредел, поэтому такие ситуации нужно проверять, ибо булево значение Infinity равно true.