Вернуть на Avito горизонтальную прокрутку изображений

На днях заметил, что Avito в течение 2 суток трижды меняло дизайн своего сайта на десктопе, каждый раз что-то добавляя новое.

Последняя серьезная их обнова по юзабитили - при увеличение изображений, прокрутка стала сверху вниз - жутко неудобно. Я Сергей, и покажу как вернуть всё назад (и дам код).

Вспомним и сравним как стало, и как было

Прокрутку изображений они сделали сверху - вниз:

Фото представлено сверху - вниз. Прокрутка стрелками влево-вправо, как было всегда, недоступна.
Фото представлено сверху - вниз. Прокрутка стрелками влево-вправо, как было всегда, недоступна.

Я не могу пользоваться такой прокруткой. Это кажется муками и пытками. Всегда уходил от такого стандарта пользования во всплывающих окнах, а тут...

Так же, отмечу, что в стандартных тематиках высокого заработка для самого Avito юзабилити алгоритм увеличения фото оставили старый, нашел это только сейчас - случайно:

Прокрутка по стандарту веба: слева направо
Прокрутка по стандарту веба: слева направо

Подозреваю, что здесь они специально не меняли прокрутку фото, так как если это приведёт к ухудшению показателей CTR, то у менеджеров этих направлений уменьшатся и их гонорары. И они догадываются что изменение стандарта юзабилити - вредит, в том числе и их выручке.

Догадки атвора))

Почему прокрутка фото сверху вниз - жутко неудобно?

После обновления дизайна и функционала увеличения фото как на первом примере, я получил большой дискомфорт и неудобство от подобного. Кроме того, сам иногда разрабатывая сайты, я не могу терпеть когда всплывающее окно, вдруг, прокручивается вверх-вниз.

Не знаю откуда это противное чувство, но явно это привито за время навигации по всем другим сайтам за долгое время. Можно сказать, пользовательский веб стандарт.

Но Avito решил пойти своим путём. Почему бы не извратить привычный юзабилити стандарт на свой манер? Ну, так, получайте (первое фото).

Скажем нет ужасному юзабилити!

Пришло время это исправить, и вернуть всё так, как это соответствует и визуалу, и пользовательским веб стандартам по привычкам пользования.

Нам понадобятся расширения для Chrome-браузеров:

  • Custom JavaScript for Websites 2
  • User CSS

И код, который мы напишем.

Анализируем код, и приступаем к действиям

Во первых, проанализируем что у нас имеется. Лента изображений вниз (нас не устраивает), это вот такой flex-контейнер:

Найден блок изображений.
Найден блок изображений.

Работа со стилями - User-CSS

Так же мы удалим эту хрень-превью слева, так как она работать не будет после изменения стилей рабочих элементов. Ниже код для User-CSS.

.styles-module-content-InRZs { flex-direction: row !important; overflow: hidden !important; } .styles-module-content-InRZs li[aria-selected="false"] { } .styles-module-root-tdwTH { display: none !important; }
  • .styles-module-content-InRZs - здесь мы меняем flex ориентацию блока на нужный нам, и на всякий случай скрываем то что можем увидеть лишнего снизу (я уже говорил про растущую нервозность когда вижу что всплывающее окно может быть прокручиваемым в любой плоскости браузера);
  • .styles-module-root-tdwTH - скрываем левый блок превью, они перестанут работать (при желании могут, но пусть это делают крутые прогеры).

Работа с кодом - Custom JavaScript for Websites 2

Не забываем сделать вот такую инъекцию библиотеки jQuery:

Если пугает слово инъекция - подключение к сайту. Этот скрипт обычно есть на 90% сайтах которые вы посещаете.
Если пугает слово инъекция - подключение к сайту. Этот скрипт обычно есть на 90% сайтах которые вы посещаете.
$(document).ready(function() { let attrid2 = 0; $('*').on("click",function(){ var attrid = -1000; if ( $(this).attr('data-id') !== undefined) { attrid = $(this).attr('data-id'); } if (attrid>=0) { attrid2 = attrid; console.log('attr get = ' + attrid); $('.styles-module-item-oasd9').css('display','none'); setTimeout(() => $('.styles-module-item-oasd9').css('display','none'), 400); setTimeout(() => $('.styles-module-item-oasd9[data-id='+attrid+']').css('display','block'), 440); } }); $(document).keyup(function(e) { if (e.keyCode === 37 || e.keyCode === 39) { if (e.keyCode === 39) { attrid2++; if ($('.styles-module-item-oasd9[data-id='+attrid2+']').length) { } else { attrid2--; } } if (e.keyCode === 37) { if (attrid2>=1) { attrid2--; } } console.log('attr get = ' + attrid2); $('.styles-module-item-oasd9').css('display','none'); $('.styles-module-item-oasd9[data-id='+attrid2+']').css('display','block'); } }); });

Коментарии по коду:

  • У нас в работе есть переменная - let attrid2, она будет позволять работать с нужным числом в двух разных функциях (с разными событиями инициализации). И хранить в памяти картинку на которой остановили листание;
  • Первое событие - это клик по любому html элементу (*) с наличием аттрибутов data-id. Если оно обнаружено, то такой атрибут пока что имеется только у превью-картинок. Оно содержит цифры от 0 до 9 или больше, что соответствует количеству доступных фото для увеличения в порядке очереди листания.
  • Так как адрес превью картинки и увеличиваемой - разные (адреса даже на разных поддоменах) и их нельзя связать (неопытному кодеру), то наш скрипт будет показывать крупную картинку с конкретным data-id соответствия от той, по которой нажали и откуда забрали data-id (нумерация превью и крупных изображений соответствует друг другу).
  • У Avito есть какая то анимация, возможно на фреймворке react-js сделанная (вывод контента сайта, типа сайт целиком можно рисовать на javascript), и при каждом увеличении фото - она запускается заново и нам нужно запустить скрытие лишних элементов с задержкой, используем таймер.
  • Один таймер на 400 ms (миллисекунд), второй - 440 ms. Первый скрывает все картинки к х**м, а второй отменяет сокрытие для той, которая имеет нужный data-id атрибут.
  • Чтобы мы могли листать картинки с 0 по конечную, нам нужен ещё и скрипт который срабатывает по нажатию стрелва влево и вправо. Я пробовал сделать это стандартным функционалом (дебаггером нашел функцию), но обнаружил опять пережатый скрипт где названия переменных и функций ужаты до одной буквы, и не стал терять время, сделал свой функционал.
  • Функция с событием keyup (что то нажали или отпустили - хз), проверяет что были нажаты именно keyCode === 37 ИЛИ 39, где 37 - вроде бы кнопка влево, а 39 - кнопка вправо (стрелки на клавиатуре). При желании, можно прикрутить и другие кнопки (wsad геймерские, ну и боковые стрелки колёсика мышки при желании).
  • И по нажатию кнопок вперёд назад что привычны почти всем пользователям веба, мы меняем стили уже без таймера для картинок.
  • Кстати, по html элементу .styles-module-item-oasd9 можно получить количество картинок, и считать это конечным числом, поэтому и у нас не будут листаться картинки дальше последней, и счётчик не будет сбиваться, так как это позволит не допускать несоответствия очерёдности переключения между картинками.

Что получили в итоге?

Картинки листаются как и хочется, туда-сюда по привычному
Картинки листаются как и хочется, туда-сюда по привычному

Я, конечно, пытался прикрутить кнопки навигации, но не тыкаю туда мышкой, поэтому не стал это делать.

Так же скрипт не идеален, ведь он работает даже когда вы не увеличиваете картинку, однако, там есть проверки, и ничего в работе сайта для стороны клиента это не ломает.

Бонус-скрипт

Так же мне не нравится, что по умолчанию поиск на Авито какой то широкий. Для меня покупка товара из других городов реальна только если это единственная возможность, а в других случаях я поеду и куплю это сам в ездовой доступности, по другому не умею.

Именно поэтому, я ещё раньше написал скрипт, чтобы можно было быстро добавлять нужные запросы к url-адресу, чтобы поиск был таким, каким я бы его делал своими руками долгое время.

Имею ввиду, что у нас появляется радиус поиска, и сортировка по дате (которая раньше убирала прочь всех вечно наверху висящих комерсантов не попадающих в свой раздел товара).

Вначале, у расширения кастом скрипт включим инъекцию библиотеки jQuery:

Размеры файлов примерно одинаковы, я взял последнюю.
Размеры файлов примерно одинаковы, я взял последнюю.

Далее, сам скрипт, копируем, и вставляем (этот можно выше или ниже первого примера):

var query = window.location.search.substring(1); console.log('query = |' + query + '|'); $(document).ready(function() { var vars = query.split("&"); var radius_adding = true; for (var i=0;i<vars.length;i++) { var pair = vars[i].split("="); if (pair[0]=='radius') {radius_adding = false;}; console.log(pair); }; var searcget = query.split("q=") + 0; console.log('yes 2 = ' + searcget.length); if (radius_adding && vars.length>1 && query!='') { //alert(vars.length); location.href = location.href + '\&radius=50\&searchRadius=50\&geoCoords=55.728812%2C37.593859\&s=104'; } else { if (radius_adding && searcget.length>=1 && query!='') { location.href = location.href + '\&radius=50\&searchRadius=50\&geoCoords=55.728812%2C37.593859\&s=104'; console.log('yes 2'); } } });

Этот скрипт писался ранее, он слегка несовершенен с точки зрения рабочей архитектуры, но функционал свой выполняет.

Работает он так, если у нас совершен поиск с главной страницы Авито (или подразделы), то обнаружив что введён запрос, запускается обновление страницы и добавляются такие параметры:

  • \&radius=50 - радиус, тут вроде понятно
  • \&searchRadius=50 - просто дублируется самим Авито, зачем - хз
  • \&geoCoords=55.728812%2C37.593859 - тут я подкинул рандомные координаты Москвы. Посмотрите свой город точку, и замените на свои
  • \&s=104 - идентефикатор сортировки. 104 соответствует сортировке по дате.

Немного оффтопа и можно ли ещё передавать цену в параметры по умолчанию?

Из особенностей, что видел, Avito передаёт ценовой параметр закодированный из цифры в длинную колбасу символов. Сделано, это видимо, чтобы затем эта колбаса обратно расшифровалась и до полной загрузки страницы поле фильтра цены были уже выставлены, но их сразу нельзя было редактировать. Возможно, оградили себя от законных подколов по цене, или что-то знают наперёд.

К слову, о ценах. Кодированные символы всегда одни и те же для одних и тех же цифр, так что алгоритм передачи цены в закодированном виде через куки/сессию/хеш или ещё что-то по идее можно расколдовать, но не нужно, так как можно взять желанную цену фильтра по умолчанию готовой колбасой символов и добавить в скрипт на своё желание.

На выходе, этот скрипт даёт возможность в один клик при поиске по сайту получать выдачу по тем условиям, которые так же у Авито были раньше стандартом. Но затем приступ коммерции, сверхприбыли сыграли такую шутку с Авито, что оно само решает за пользователями что они будут находить или не будут, и опыты без уведомления над ими же.

Что было упущено при разработках?

На моменте скрининга я случайно обнаружил, что в недвижимости они оставили старый функционал увеличения фото. Чувствую, что здесь они несут убытки, если ухудшают функционал, и тут тесты их отделу разработки не одобряют. Но не это нас интересует.

А интересно здесь то, что можно в их толпе кода обнаружить какая функция или протокол (забыл слово, когда кусок массива функций объеденяют в один блок, к которому можно обращаться не как к функции, а иначе) отвечает за горизонтальную прокрутку, и применять это для всех типов товара. И тогда доработки кастом не потребуются.

Но доработки сделаны, они успешно функционируют. Хотя рано или поздно идентефикаторы элементов могут изменяться, тогда нужно будет обращаться к ним по dom-структуре вложенности, либо дописать парсер, который будет обновлять эти идентификаторы в случае сбоя обнаружения их на странице.

Всем спасибо. Подпишись на эту телегу - 🛒!

Начать дискуссию