Front-end разработка визуальной части онлайн-калькулятора
Интерфейс разработан под стилистику сайта заказчика. Были взяты цвета, шрифты и т. д. гармонирующие между собой и стилями сайта. Стили (CSS) и javascript код были написаны в отдельных файлах для более быстрой и правильной загрузки сайта. По этой же причине была подключена библиотека jQuery (javascript библиотека). Используется flex разметка для того, чтобы вёрстка отображалась на всех экранах и устройствах читабельно и красиво.
CSS (англ. Cascading Style Sheets — каскадные таблицы стилей) — технология описания внешнего вида документа, оформленного языком разметки. Преимущественно используется как средство оформления веб-страниц в формате HTML и XHTML, но может применяться с любыми видами документов в формате XML, включая SVG и XUL.
Был добавлен файл стилей "calculate.css" :
.wrapper-calculater .form-calculator,
.wrapper-calculater .form-parser {
width: 100%;
padding: 10px;
display: flex;
-webkit-box-flex: flex;
-webkit-box-align: center;
-webkit-box-direction: normal;
align-items: center;
justify-content: center;
flex-flow: row wrap;
}
.wrapper-calculater {
width: 100%;
margin: 10px 0;
display: flex;
-webkit-box-flex: flex;
-webkit-box-align: start;
-webkit-box-direction: normal;
align-items: flex-start;
justify-content: center;
flex-flow: row wrap;
}
.wrapper-calculater .form-calculator .promtex-group,
.wrapper-calculater .form-parser .promtex-group {
display: flex;
align-items: flex-start;
-webkit-box-flex: flex;
-webkit-box-align: stretch;
-webkit-box-orient: horizontal;
-moz-box-flex: flex;
-moz-box-align: start;
-moz-box-orient: horizontal;
justify-content: space-between;
flex-flow: column wrap;
margin: 5px 0;
}
.wrapper-calculater .form-calculator .promtex-uzo {
display: none;
}
.wrapper-calculater .form-calculator .promtex-submit-wrapper,
.wrapper-calculater .form-parser .promtex-submit-wrapper {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin: 10px auto;
}
.wrapper-calculater .form-calculator .promtex-group label,
.wrapper-calculater .form-parser .promtex-group label {
margin-bottom: 5px;
font-weight: 600;
font-size: 17px;
}
.select-promtex, .wrapper-calculater .form-calculator .promtex-group input,
.wrapper-calculater .form-parser .promtex-group input {
font-size: 16px;
font-weight: 400;
width: 99%;
display: block;
padding: 4px;
border: none;
background-color:bisque;
}
.wrapper-calculater .form-calculator .promtex-group-radiobtn,
.wrapper-calculater .form-parser .promtex-group-radiobtn {
flex-flow: row wrap;
justify-content: flex-start;
}
.wrapper-calculater .form-calculator .promtex-group-radiobtn label,
.wrapper-calculater .form-parser .promtex-group-radiobtn label {
display: inline-block;
width: 100%;
}
.wrapper-calculater .form-calculator .promtex-group-radiobtn input,
.wrapper-calculater .form-parser .promtex-group-radiobtn input {
width: 5%;
margin-right: 4px;
margin-top: 6px;
}
#width_schits_second {
display: none;
}
.main_calculate {
width: 100%;
max-width: 1000px;
}
.calc-promtex-block {
display: flex;
align-items: flex-start;
justify-content: space-between;
flex-flow: row wrap;
}
.calc-promtex-block a {
display: block;
width: 47%;
}
.calc-promtex-block p {
width: 50%;
padding-right: 5px;
}
.promtex-submit-wrapper .parser-run-btn,
.calc-promtex-btn {
padding: 10px 15px;
border-radius: 15px;
border: none;
background: linear-gradient(#2165a1 75%, #e4e2 10% , #2165a1 25%);
-webkit-background-clip: border-box;
-moz-background-clip: content-box;
color: #fff;
margin: 10px auto;
cursor: pointer;
}
.promtex-submit-wrapper .calc-promtex-btn {
margin: 10px;
}
#vstroikas {
display: none;
}
.calc-promtex-btn:hover,
.promtex-submit-wrapper .parser-run-btn:hover,
.calc-promtex-btn::-moz-focus-inner,
.calc-promtex-btn::-webkit-inner-spin-button {
background: #919191;
-webkit-animation: normal;
-webkit-backdrop-filter: #919191;
}
.wrapper .content .main_calculate .entry {
padding-left: 0;
padding: 10px;
}
.promtex-result-wrapper h4 {
font-size: 22px;
font-weight: 700;
display: block;
width: 100%;
text-align: center;
padding-bottom: 10px;
}
.promtex-result-wrapper {
width: 100%;
margin: 10px 0;
padding: 10px;
display: block;
background-color: #f3f3f2;
border: 1px solid #2165a1;
border-radius: 5px;
}
.podpiska {
font-size: 12px;
text-align: right;
}
.promtex-result,
.promtex-result-parser {
width: 100%;
padding: 10px;
margin: -10px;
display: none;
align-items: flex-start;
justify-content: flex-start;
flex-flow: column wrap;
}
.promtex-result span,
.promtex-result-parser span {
text-align: center;
width: 100%;
}
.slabotok {
display: none;
}
HTML (от англ. HyperText Markup Language — «язык гипертекстовой разметки») — стандартизированный язык разметки документов во Всемирной паутине. Большинство веб-страниц содержат описание разметки на языке HTML (или XHTML). ... Спецификации HTML5 формулируются в терминах DOM (объектной модели документа).
HTML-код формы онлайн-калькулятора:
<div class="wrapper-calculater">
<!-- Форма заполнения данных для обработки -->
<form name="sh-e-calculator" action="" id="form-sh-calc" class="form-calculator" method="post">
<div class="promtex-group-radiobtn promtex-group">
<label for="slabo_tok">Наличие слаботочного отсека</label>
<input id="slabo_tok_true" required type="radio" class="prmtex promtex-radio" value="1" name="slabo_tok">Да
<input id="slabo_tok_false" required type="radio" class="prmtex promtex-radio" value="0" name="slabo_tok">Нет
</div>
<div class="promtex-group-radiobtn promtex-group">
<label title="(УЗО, диф. Автомат)" for="diff_shield">Наличие дифференциальной защиты</label>
<input id="uzo_true" required title="УЗО и диф. Автомат будут по выбору" type="radio" class="prmtex promtex-radio" value="1" name="diff_shield">Да
<input id="uzo_false" required title="УЗО и диф. Автомат будут по выбору" type="radio" class="prmtex promtex-radio" value="0" name="diff_shield">Нет
</div>
<div class="promtex-group">
<label for="variant_install">Выберите способ установки щита</label>
<select class="prmtex select-promtex" required="required" name="variant_install" id="variant_install">
<option selected >-</option>
<?php foreach ($views as $view): ?>
<option value="<?php echo $view["id_view"]; ?>"><?php echo $view["name_view"]; ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="promtex-group">
<label for="width">Выберите размер щита (мм)</label>
<select id="width" class="prmtex select-promtex" required="required" name="width">
<option>-</option>
<option id="vstroikas" class="slabotok vstroika" title="для встраиваемых" value="1000х930х135">ниша 900х830х135 мм, внешний размер 1000х930х135 мм</option>
<option id="vstroikas-2" class="not-slabotok vstroika" title="для встраиваемых" value="1000х580х135">ниша 900х480х135 мм, внешний размер 1000х580х135 мм</option>
<option id="navesnoy" class="slabotok naves" value="940х870х130">внешний размер 940х870х130 мм</option>
<option id="navesnoy-2" class="not-slabotok naves" value="900х600х130">внешний размер 900х600х130 мм</option>
<option id="unique_width" value="unique_width">Нестандарт</option>
</select>
</div>
<div class="promtex-group">
<label for="kolvo_sh_kvartir">Введите количество квартир в ЩЭ</label>
<select class="prmtex select-promtex" required="required" name="kolvo_sh_kvartir" id="kolvo_sh_kvartir">
<option selected >-</option>
<?php for ($i = 1; $i <= 9; $i++): ?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php endfor; ?>
</select>
</div>
<div class="promtex-group">
<label for="nominal_tok">Номинальный ток вводного аппарата на квартиру</label>
<select required="required" title="Автоматы будут в любом случае на каждую квартиру" class="prmtex select-promtex" name="nominal_tok" id="nominal_tok">
<option selected >-</option>
<?php foreach ($nominal as $nom): ?>
<option title="Автоматы будут в любом случае на каждую квартиру" value="<?php echo $nom["id_nominal"]; ?>"><?php echo $nom["view_nominal"]."А"; ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="promtex-group">
<label for="product_develop_modul">Выберите производителя модульной автоматики</label>
<select required="required" title="Список производителей" class="prmtex select-promtex" name="product_develop_modul" id="product_develop_modul">
<option selected >-</option>
<?php foreach ($procreators as $procreat): ?>
<option value="<?php echo $procreat["id_procreator"]; ?>">
<?php echo $procreat["name_procreator"]; ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="promtex-group">
<label for="product_develop_schetchik">Выберите производителя счетчиков эл. энергии</label>
<select title="" required="required" class="prmtex select-promtex" name="product_develop_schetchik" id="product_develop_schetchik">
<option selected >-</option>
<?php foreach ($schetchiks as $schet):?>
<option value="<?php echo $schet["schetchik_id"]; ?>">
<?php echo $schet["schetchik_procreator"]; ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="promtex-group">
<label for="kol_vo_shields">Укажите количество щитов в заказе (шт)</label>
<input class="prmtex" required="required" name="kol_vo_shields" default-value="0" min="1" id="kol_vo_shields" type="number">
</div>
<!-- Кнопки для результатов и очистки формы -->
<div class="promtex-submit-wrapper">
<button name="razchet" type="submit" id="calc-summ" class="calc-promtex-btn disable" disabled>Рассчитать стоимость</button>
<button name="clear-calc" type="button" class="calc-cancel calc-promtex-btn">Очистить</button>
</div>
<!-- /Кнопки для результатов и очистки формы -->
</form>
<!-- /Форма заполнения данных для обработки -->
<!-- Вывод результатов -->
<div class="promtex-result-wrapper">
<h4 class="text-center">Результаты расчётов</h4>
<div class="promtex-result">
</div>
</div>
<!-- /Вывод результатов -->
</div>
</div>
Рисунок 1 - Вид онлайн-калькулятора
На основании данных и предварительной вёрстке пришли к общему дизайну калькулятора (рис. 1). Валидация формы (рис. 2) - при учёте того, что там выпадающие списки, невозможно ввести свои значения, как в текстовое поле, также использованы и числовые поля. Ограничения ввода данных и отключение кнопки для вычислений пока пользователь не внесет все данные для расчета.
Рисунок 2 - Валидация онлайн-калькулятора
Валидация происходит на языке javascript для того, чтобы проверка выбора и заполнения данных была динамической (происходила сразу же без перезагрузки страницы).
Код валидации формы:
//переключение варианта установки
$('#variant_install').change(function () {
if ($(this).val() == 1) {
$('#width').prop('selectedIndex', 0);
$('#vstroikas').fadeIn();
$('.vstroika').fadeIn();
$('#navesnoy').fadeOut();
$('.naves').fadeOut();
} else if ($(this).val() == 2) {
$('#width').prop('selectedIndex', 0);
$('.vstroika').fadeOut();
$('#vstroikas').fadeOut();
$('.naves').fadeIn();
$('#navesnoy').fadeIn();
}
});
// Проверка полей формы до отправки данных
$('#variant_install').on('blur', function (){
if ($(this).find(':selected').index() == 0) {
$(this).removeClass('valid');
$(this).addClass('invalid');
$('#calc-summ').addClass('disable');
$('#calc-summ').prop('disabled',true);
} else {
$(this).removeClass('invalid');
$(this).addClass('valid');
}
});
$('#width').on('blur', function (){
if ($(this).find(':selected').index() == 0) {
$(this).removeClass('valid');
$(this).addClass('invalid');
$('#calc-summ').addClass('disable');
$('#calc-summ').prop('disabled',true);
} else {
$(this).removeClass('invalid');
$(this).addClass('valid');
}
});
$('input[name='slabo_tok']').change(function () {
if ($(this).val() == 1 ) {
$('.not-slabotok').fadeOut();
$('.not-slabotok').prop('disabled', true);
$('.slabotok').fadeIn();
$('.slabotok').prop('disabled', false);
if ($('#variant_install').val() == 1) {
$('#width').prop('selectedIndex', 0);
$('#vstroikas').fadeIn();
$('.vstroika').fadeIn();
$('#navesnoy').fadeOut();
$('.naves').fadeOut();
} else if ($('#variant_install').val() == 2) {
$('#width').prop('selectedIndex', 0);
$('.vstroika').fadeOut();
$('#vstroikas').fadeOut();
$('.naves').fadeIn();
$('#navesnoy').fadeIn();
}
} else if ($(this).val() == 0 ) {
$('.not-slabotok').prop('disabled', false);
$('.not-slabotok').fadeIn();
$('.slabotok').fadeOut();
$('.slabotok').prop('disabled', true);
if ($('#variant_install').val() == 1) {
$('#width').prop('selectedIndex', 0);
$('#vstroikas').fadeIn();
$('.vstroika').fadeIn();
$('#navesnoy').fadeOut();
$('.naves').fadeOut();
} else if ($('#variant_install').val() == 2) {
$('#width').prop('selectedIndex', 0);
$('.vstroika').fadeOut();
$('#vstroikas').fadeOut();
$('.naves').fadeIn();
$('#navesnoy').fadeIn();
}
}
});
$('#kolvo_sh_kvartir').on('blur', function (){
if ($(this).find(':selected').index() == 0) {
$(this).removeClass('valid');
$(this).addClass('invalid');
$('#calc-summ').addClass('disable');
$('#calc-summ').prop('disabled',true);
} else {
$(this).removeClass('invalid');
$(this).addClass('valid');
}
});
$('#nominal_tok').on('blur', function (){
if ($(this).find(':selected').index() == 0) {
$(this).removeClass('valid');
$(this).addClass('invalid');
$('#calc-summ').addClass('disable');
$('#calc-summ').prop('disabled',true);
} else {
$(this).removeClass('invalid');
$(this).addClass('valid');
}
});
$('#product_develop_modul').on('blur', function (){
if ($(this).find(':selected').index() == 0) {
$(this).removeClass('valid');
$(this).addClass('invalid');
$('#calc-summ').addClass('disable');
$('#calc-summ').prop('disabled',true);
} else {
$(this).removeClass('invalid');
$(this).addClass('valid');
}
});
$('#product_develop_schetchik').on('blur', function (){
if ($(this).find(':selected').index() == 0) {
$(this).removeClass('valid');
$(this).addClass('invalid');
$('#calc-summ').addClass('disable');
$('#calc-summ').prop('disabled',true);
} else {
$(this).removeClass('invalid');
$(this).addClass('valid');
$('#calc-summ').removeClass('disable');
$('#calc-summ').prop('disabled',false);
}
});
После согласования вывод результата расчетов осуществляется в таком порядке:
- Щит - тип щита, размер;
- Защитные устройства (автоматы) - название устройства;
- Учёт - название счётчика электроэнергии;
- Цены - цена одного щита, общая сумма.
Выбор данных осуществляется из базы данных по выбору пользователя, то есть если выбран производитель Энергомера, то его название и будет выводиться, соответственно и его цена будет браться для расчетов.
Значения, выбранные пользователем в форме, после нажатия на кнопку “рассчитать” отправляются на сервер и получают ответ через ajax-запрос и выводят его в отдельный html блок с данными расчетов и выводится на странице калькулятора.
Код отправки данных на сервер для подсчета результатов:
//Обработчик формы ajax-запросом и отправка данных в виде html
$('#form-sh-calc').submit(function (e){
event.preventDefault();
event.stopPropagation();
var form = $('#form-sh-calc');
var sl_tok = $('input[name='slabo_tok']:checked').val();
var uzo = $('input[name='diff_shield']:checked').val();
var variant_install = $('#variant_install').val();
var width_schits = $('#width').val();
var kolvo_sh_kvartir = $('#kolvo_sh_kvartir').val();
var nominal_tok = $('#nominal_tok').val();
var product_develop_modul = $('#product_develop_modul').val();
var product_develop_schetchik = $('#product_develop_schetchik').val();
var kol_vo_shields = $('#kol_vo_shields').val();
if (!sl_tok || !uzo || !variant_install || !width_schits || !kolvo_sh_kvartir
|| !nominal_tok || !product_develop_modul || !product_develop_schetchik || !kol_vo_shields) {
$('#calc-summ').prop('disabled',true);
} else {
$('#calc-summ').prop('disabled',false);
}
var url = '/calculators/summa.php';
$.ajax({
url: url,
data: {
'slabo_tok': sl_tok,
'uzo': uzo,
'install': variant_install,
'width': width_schits,
'kolvo_kvartir': kolvo_sh_kvartir,
'nominal': nominal_tok,
'product_modul': product_develop_modul,
'kolvo_shields': kol_vo_shields,
'schetchik': product_develop_schetchik
},
type: $('#form-sh-calc').attr('method'),
success: function(data,response) {
$('.promtex-result').html(data);
$('.promtex-result').fadeIn(600);
$('.promtex-result').css({'display':'flex'});
$('html, body').animate({
scrollTop: $('.promtex-result-wrapper').offset().top
}, 1000);
}
});
});
Рисунок 3 - Результаты расчетов онлайн-калькулятора