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 - Результаты расчетов онлайн-калькулятора