Front-end разработка визуальной части калькулятора стоимости монтажа кабельных лотков
Интерфейс разработан под стилистику сайта. Были взяты цвета, шрифты и т. д. гармонирующие между собой и стилями сайта. Стили (CSS) и javascript код были написаны в отдельных файлах для более быстрой и правильной загрузки сайта. По этой же причине была подключена библиотека jQuery (javascript библиотека). Используется flex разметка для того, чтобы вёрстка отображалась на всех экранах и устройствах читабельно и красиво.
Для разработки front-end стороны были использованы знания такие как: HTML5.0 (язык гипертекстовой разметки), CSS3 (каскадные таблицы стилей), Javascript (, jQuery. Так как в прошлом калькуляторе уже создали “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; } .promtex-table tr td ul { list-style: none; color: inherit; width: 100%; } .promtex-table tr td ul li { list-style: none; width: 100%; } .promtex-table tr td ul li span a { margin-left: 3px; text-decoration: none; color: inherit; font-weight: 600; cursor: not-allowed; } .promtex-table tr td ul li span { width: 100%; margin: 0 3px; } .modal-message { display: none; position: absolute; top: 45%; left: 45%; background-color: #fff; color: #000; border-radius: 15px; padding: 10px; } .invalid { border: 1px solid #850808; } .valid { border: 1px solid #0e680533; } .disable { background: #a11c1c; } .disable:hover { background: #a11c1c; } .entry .promtex-vacancies-item { width: 100%; padding: 10px; flex-flow: column wrap; } .entry .promtex-vacancies-item p { padding: 3px; margin-bottom: 5px; line-height: 1.25; width: 100%; } .entry .promtex-vacancies-item .ul-flex { width: 100%; margin: 3px auto; display: flex; align-items: flex-start; justify-content: flex-start; flex-flow: row wrap; } .promtex-vacancies-item a { display: inline; } #pars-table { width: 93%; margin: 0 auto; word-wrap: break-word; text-align: center; font-size: 13px; } #pars-table thead tr th { padding: 3px; text-align: center; border: 1px solid #919191; } .calc-cancel { background: linear-gradient(#a95e5ebf 75%, #e2bee222 10% , #a95e5ebf 25%); color: #fff; } .img-responsive { width: 100%; display: block; height: auto; } .wrapper-entry-content { display: flex; align-items: flex-start; justify-content: center; flex-flow: row wrap; padding: 10px; position: relative; } .wrapper-entry-content p { width: 100%; line-height: 1.35; padding: 0; margin: 0 0 5px; } .wrapper-entry-content a { text-decoration: none; } .wrapper-entry-content a .img-title { text-align: center; padding-top: 0; text-decoration: none; color: #000; margin-bottom: 10px; } .wrapper-entry-content pre { background-color: #2165a1; color: #fff; width: 100%; height: auto; max-height: 300px; overflow: auto; cursor: text; margin: 10px 0; } .entry .wrapper-entry-content .view-code { width: auto; max-width: 100vh; height: 500px; max-height: 100%; overflow: auto; overflow-x: scroll; background: #2165a1; display: block; position: absolute; left: 0; top: 0; z-index: 999; } .entry .wrapper-entry-content .code { width: 100%; padding: 5px 0; background-color: #919191; border: 0.5px solid #2165a1; margin-bottom: 10px; } .entry .wrapper-entry-content ol { width: 100%; } .entry .wrapper-entry-content ol li:before { color: inherit; font-weight: 600; } .promtex-li-span { width: 100%; display: block; padding: 3px 5px; line-height: 1.25; } .entry .wrapper-entry-content h3 { margin-right: auto; line-height: 1.35; margin-top: 10px; } .table-container { min-width: 320px; max-width: 100%; padding: 0 15px; box-sizing: border-box; padding: 10px; } .table-container table { border-collapse: collapse; width: 100%; margin: 0; margin-bottom: 10px; } .table-container table td, .table-container table th { padding: 5px; border: 1px solid #cbbdbd; } .table-container tr:nth-child(even){ background-color: #2165a1; color: #fff; } .fade { display: block; } .hide { display: none; } .table-container td a { color: inherit; } .table-container td a:hover { color: #850808; } @media only screen and (max-width: 720px) { .table-container table thead { display: none; } .table-container table tr { display: block; } .table-container table td { display: flex; justify-content: space-between; font-size: 14px; } .table-container table td::before { content: attr(data-label); font-weight: bold; margin-right: 20px; } } @media only screen and (min-width: 768px) { .entry .promtex-vacancies-item .ul-flex li { width: 45%; } .table-container { width: 100%; } .table-container .table-title { margin-top: 5px; margin-bottom: 2px; } .entry .promtex-vacancies-item .ul-flex >:last-child { width: 100%; } .wrapper-calculater .form-calculator .promtex-group, .wrapper-calculater .form-parser .promtex-group { width: 100%; margin: 5px; } .wrapper-calculater .form-calculator, .wrapper-calculater .form-parser { width: 45%; margin: 0 auto; } .header nav ul li:hover > ul { display: block; width: 300px; } .promtex-result-wrapper { width: 50%; margin: 10px auto; } .wrapper-calculater { flex-flow: column wrap; } }
После этого согласуем внешний вид формы калькулятора для ввода и выбора данных. Для защиты от ошибок со стороны пользователя или иных угроз. Используем выпадающие списки и числовые поля ввода (input type=”number” ).
Также для защиты делаем проверку данных и производим все расчёты на серверной стороне.
- Тип лотка (нужно вначале выбрать тип лотка, чтобы можно было понимать какие лотки брать из базы данных)
- Количество углов.
- Длина прямых участков (в метрах, цена берётся за 1 м, но в магазинах идёт покупка от 3 метров)
- Ширина (берется в мм, от 50 мм до 600 мм)
- Высота (мм, от 35 до 100)
- Наличие крышки (да или нет).
- Покрытие лотка ( берем два покрытия горячеоцинкованное или холодное цинкование).
Теперь посмотрим на визуальность (рисунок 1). Все поля данных идут строго по порядку, чтобы все данные были заполнены поочерёдно.
Проверка всех выбранных и введенных данных. Также неактивность кнопки пока не будут добавлены или выбраны все необходимые для расчета данные. Также если нужно очистить данные есть кнопка для этого, если вы ошиблись или выбор сделан неправильный.
Рисунок 2 - Пример работы валидации формыПроисходит валидация на javascript языке, с помощью и упрощением разработки библиотеки jQuery. Вот код валидации:
$('#height_lotka').on('blur', function () { if ($(this).find(':selected').index() == 0) { $(this).removeClass('valid'); $(this).addClass('invalid'); $('.calc-lotki-result').addClass('disable'); $('.calc-lotki-result').prop('disabled',true); } else { $(this).removeClass('invalid'); $(this).addClass('valid'); } }); $('#width_lotka').on('blur', function (){ if ($(this).find(':selected').index() == 0) { $(this).removeClass('valid'); $(this).addClass('invalid'); $('.calc-lotki-result').addClass('disable'); $('.calc-lotki-result').prop('disabled',true); } else { $(this).removeClass('invalid'); $(this).addClass('valid'); } }); $('#type_lotok').on('blur', function (){ if ($(this).find(':selected').index() == 0) { $(this).removeClass('valid'); $(this).addClass('invalid'); $('.calc-lotki-result').addClass('disable'); $('.calc-lotki-result').prop('disabled',true); } else { $(this).removeClass('invalid'); $(this).addClass('valid'); } }); $('#type_lotok').on('change', function (){ if ($(this).val() == 1) { $('#width_lotka').prop('selectedIndex', 0); $('#height_lotka').prop('selectedIndex', 0); $('#h-2').removeClass('hide'); $('#h-3').removeClass('hide'); $('#w-1').removeClass('hide'); $('#w-2').removeClass('hide'); $('#w-3').removeClass('hide'); $('#w-4').removeClass('hide'); $('#w-5').removeClass('hide'); $('#w-6').removeClass('hide'); $('#w-7').removeClass('hide'); $('#w-8').removeClass('hide'); $('#w-9').removeClass('hide'); $('#h-5').removeClass('hide'); $('#h-1').removeClass('hide'); $('#h-5').addClass('hide'); $('#h-1').addClass('hide'); // При выборе ширины меньше 100 $('#width_lotka').on('blur', function (){ if ($('#width_lotka').val() == 9) { $('#h-3').addClass('hide'); $('#h-4').addClass('hide'); } else { $('#h-3').removeClass('hide'); $('#h-4').removeClass('hide'); } if ($('#width_lotka').val() == 1) { $('#h-2').addClass('hide'); $('#h-4').addClass('hide'); } else { $('#h-2').removeClass('hide'); $('#h-4').removeClass('hide'); } }); } else if ($(this).val() == 2) { $('#height_lotka').prop('selectedindex', 0); $('#width_lotka').prop('selectedIndex', 0); $('#h-5').removeClass('hide'); $('#h-1').removeClass('hide'); $('#h-5').addClass('hide'); $('#w-9').addClass('hide'); $('#w-1').addClass('hide'); } else if ($(this).val() == 3) { $('#width_lotka').prop('selectedIndex', 0); $('#height_lotka').prop('selectedIndex', 0); $('#h-5').removeClass('hide'); $('#w-9').removeClass('hide'); $('#w-1').removeClass('hide'); $('#h-2').removeClass('hide'); $('#h-3').removeClass('hide'); $('#w-1').removeClass('hide'); $('#w-2').removeClass('hide'); $('#w-3').removeClass('hide'); $('#w-4').removeClass('hide'); $('#w-5').removeClass('hide'); $('#w-6').removeClass('hide'); $('#w-7').removeClass('hide'); $('#w-8').removeClass('hide'); $('#w-9').removeClass('hide'); $('#h-5').removeClass('hide'); $('#h-1').addClass('hide'); $('#w-9').addClass('hide'); $('#w-1').addClass('hide'); $('#w-2').addClass('hide'); $('#w-3').addClass('hide'); $('#w-9').addClass('hide'); $('#h-5').addClass('hide'); } else if ($(this).val() == 4) { $('#width_lotka').prop('selectedIndex', 0); $('#height_lotka').prop('selectedIndex', 0); $('#w-9').removeClass('hide'); $('#w-1').removeClass('hide'); $('#w-2').removeClass('hide'); $('#w-3').removeClass('hide'); $('#h-5').removeClass('hide'); $('#h-1').addClass('hide'); $('#height_lotka').on('blur', function (){ if ($('#height_lotka').val() == 3) { $('#w-9').addClass('hide'); } else { $('#w-9').removeClass('hide'); } }); } else { $('#height_lotka').find(':selected').index().each(function (){ $(this).fadeIn(); $(this).removeClass('hide'); }); $('#width_lotka').find(':selected').index().each(function (){ $(this).fadeIn(); $(this).removeClass('hide'); }); } }); $('#pokryitie_lotka').on('blur', function (){ if ($(this).find(':selected').index() == 0) { $(this).removeClass('valid'); $(this).addClass('invalid'); $('.calc-lotki-result').addClass('disable'); $('.calc-lotki-result').prop('disabled',true); } else { $(this).removeClass('invalid'); $(this).addClass('valid'); $('.calc-lotki-result').removeClass('disable'); $('.calc-lotki-result').prop('disabled',false); } });
После отправки данных на сервер, по полученным данным идет выбор данных о лотке, крышке, углах и их цены, потом используются формулы, приведенные в статье, где описано техническое задание. Вывод результатов осуществляем в таком порядке:
- Тип лотка
- Длина прямых участков (если выбран 1 или 2 метра , то в расчётах берётся 3)
- Стоимость 1-ого угла
- Стоимость 1 метра лотка
- Сумма стоимости работ
- Общая сумма