Привет всем! Меня зовут Александр, я отвечаю за техническую часть всех проектов студии. За креатив у нас отвечает Тима, который однажды предложил мне идею сделать оригинальный подбор тарифов на нашем сайте.

Этот пост про разработку, но я позволю себе небольшое предисловие, без которого он не будет цельным. Так как я рос в 90-ые, то прекрасно помню рекламные креативы тех времён: они были смелые, вызывающие и дерзкие. Таких сейчас не встретишь. Но среди яркой рекламы, были и просто оригинальные, запоминающиеся идеи. Одной из таких, увиденных мной, была обычная рекламная листовка на столбе. Где бригада строителей предлагала «сделать ремонт любой сложности» с условием, что можно выбрать только две опции из трёх, опции были такими:
- быстро
- качественно
- дёшево
Путём нехитрых вычислений, к потенциальным клиентам данных строителей быстро приходило понимание, что одновременно «быстро, качественно и дёшево» не бывает. Мне тогда эта реклама понравилась, я про неё благополучно забыл и никак не ожидал, что подобная идея всплывёт, спустя несколько десятилетий.
Итак, подошёл я к реализации идеи Тимы сначала «в лоб» самым простым способом - взять готовую JS-библиотеку и адаптировать её под свои задачи. Однако, одна из популярных библиотек - JqueryUI.slider, имела ряд ограничений, самым важным из которых оказалось отсутствие поддержки некоторыми мобильными устройствами.
Изобретать велосипед я всё ещё не хотел и следующей на очереди библиотекой была noUIslider. Ирония в том, что библиотека с приставкой noUI в визуальном плане и в поддержке устройств оказалась гораздо лучше первой :)
Первое, что я сделал, это сверстал макет с 3 ползунками внутри и добавил ниже поля, в которых будет меняться текст, в зависимости от выбранных значений:
<div class="maxwidth-theme"><a name="tariffs"></a> <h3 class="index-block__title switcher-title">Хорошо, быстро, дёшево, выбери два</h3> <div class="wrapper"> <div class="slider-text-wrapper"> <div class="slider-text"></div> <div class="slider-title"><i class="fa big-icon grey s30 fa-check-square"></i>Качество</div> <div class="slider-text"></div> </div> <div class="slider-1" id="qual" data-slider></div> </div> <div class="wrapper"> <div class="slider-text-wrapper"> <div class="slider-text"></div> <div class="slider-title"><i class="fa big-icon grey s30 fa-calendar"></i>Срок выполнения (мес.)</div> <div class="slider-text"></div> </div>
<div class="slider-2" id="time" data-slider></div> </div> <div class="wrapper"> <div class="slider-text-wrapper"> <div class="slider-text"></div> <div class="slider-title"><i class="fa big-icon grey s30 fa-rub"></i>Цена в месяц (₽)</div> <div class="slider-text"></div> </div>
<div class="slider-3" id="price" data-slider></div> </div>
<div class="col-md-12"> <div class="sum"> <blockquote>Стоимость проекта <div class="month-price" id="tarif"> </div> </blockquote> </div>
На сайте этот блок выглядит так:

Сами ползунки находятся внутри блоков с классами slider-1, slider-2 и slider-3, каждому из которых присвоены id: qual, time и price. Сначала на каждой шкале ползунка я разместил минимальные и максимальные значения, но далее от этой идеи пришлось отказаться, так как сроки и цена проектов динамически изменяются в зависимости от выбранного качества.
Также я добавил иконки и прописал стили для ползунков и текста. Так как скрипт у нас работает внутри Битрикса, то часть стилей (для иконок) удалось заимствовать из темы, остальные я добавил самостоятельно:
.noUi-horizontal .noUi-handle { width: 34px; height: 28px; right: -17px; top: -6px; }
.noUi-touch-area { height: 100%; margin: 0 auto; }
.noUi-handle { border: none; border-radius: initial; background: transparent; cursor: grab; box-shadow: none; }
.list { position: relative; }
.list::before { content: "Так не бывает!"; position: absolute; left: 0; opacity: 0; visibility: hidden; top: 0; width: 100%; height: 100%; display: flex; justify-content: flex-start; align-items: center; background-color: #fff; font-weight: bold; }
.list.no::before { opacity: 1; visibility: visible; z-index: 99; }
На странице с тарифами подключаем библиотеку:
<script src="js/nouislider.min.js"></script>
Теперь можем перейти к самому скрипту. В первую очередь, выбираем все три ползунка и создаем из них константы, чтобы далее не писать лишний код:
const qual = document.querySelector('#qual');
const time = document.querySelector('#time');
сonst price = document.querySelector('#price');
Далее создаём все три шкалы и задаём их свойства:
if(qual && time && price) {
noUiSlider.create(qual, {
start: 4,
behaviour: 'smooth-steps-tap',
step: 1,
connect: [true, false],
range: {
'min': 1,
'max': 5
}
});
noUiSlider.create(time, {
start: 4,
behaviour: 'smooth-steps-tap',
step: 1,
connect: [true, false],
range: {
'min': 1,
'max': 12
}
});
noUiSlider.create(price, {
start: 1,
behaviour: 'smooth-steps-tap',
step: 1,
connect: [true, false],
range: {
'min': 30000,
'max': 90000
},
format: wNumb({
decimals: 3,
thousand: '.'
})
})
Теперь началось самое интересное! Мне нужно было понять и прописать зависимости ползунков друг от друга. Признаюсь честно, на подбор правильной логики я потратил несколько дней. Первый вариант заключался в том, что на шкале цен я создал все возможные вариации цен и ползунок должен был перемещаться по ним. Потом я понял, что в разных тарифах цены не делятся на одно число и разбить их ровно по одной шкале не получается.
Второй вариант логики состоял в том, чтобы изменять шкалу цен динамически, в зависимости от выбранного тарифа. Но теперь загвоздка была в том, что и сроки в тарифах отличаются. Самый простой тариф не имеет смысла растягивать на 3 и более месяцев. В итоге мне пришлось переписать логику изменения цен и сделать новые зависимости шкалы цен и месяцев для каждого из тарифов. Фух, ползунки наконец заработали как надо!
Ещё какое-то время ушло на то, чтобы понять, что на шкале цен правильнее и понятнее отображать цену в месяц, а итоговую стоимость проекта и скидку рассчитывать в отдельном блоке под ползунками. Сначала я сделал простую функцию умножения цены на количество месяцев, но и её пришлось переписать и для каждого тарифа считать скидку отдельно.
В итоге, казалось бы для простой задачи, суммарно было написано более 1000 строк кода. Изменения затронули файлы JS и CSS в теме Битрикс, была создана включаемая область для блока на главной.

P.S. для разбивки чисел на разряды и улучшения восприятия цен была использована библиотека wNumb:
<script src="js/wNumb.min.js"></script>