Лиллипуттен унд Нобле Артефакты 2015

Галерея обложек с динамической подгрузкой на AJAX

Реализуем прокрутку изображений (обложек дисков) для сайта boogiemanmusic с динамической подгрузкой данных на AJAX.

Исходные файлы:

  • Минимальный код на страничке (подключение стилей, скрипта, контейнер): Content-Coverselle.html;
  • Скрипт (coffeescript, использует jQuery): js/Coverselle.coffee;
  • Стили (LESS, наследует определения из bootstrap, включено в архив; см.ниже): css/Coverselle.less;
  • AJAX-сервер (PHP-скрипт, демо-заглушка): coverselle-load.php.

Демо:

Возможные задачи на доработку:

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

Информация из документации для программистов (markdown на bitbucket.org):

См. пример на демо-сайте (логин/пароль: demo/demo).

Составные файлы модуля:

  • Content-Coverselle (.eco, .html) — демо-макет.
  • css/Coverselle (.less, .css) — стили.
  • js/Coverselle (.coffee, .js) — скрипты.
  • coverselle-load.php — пример серверного скрипта для загрузки данных обложек для показа.

Структура HTML:

В самом коде располагается пустой контейнер, в который потом динамически загружаются данные:

<div class="Coverselle"></div>

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

Показ знака во время загрузки убран, т.к. сам механизм загрузки изменён (см. ниже).

После первой загрузки показываются и инициализируются кнопки перелистывания «вперёд/назад».

Во время каждой загрузки создаётся новый вложенный контейнер .box, в который добавляются элементы обложек.

Генерируемый код для каждой обложки выглядит следующим образом:

<item class="dist#{dist}" data-link="#{params.items[count].link}" data-image="#{params.items[count].cover}">
    <item-info>
        <item-artist>#{params.items[count].artist}</item-artist>
        <item-name>#{params.items[count].title}</item-name>
        <item-more><item-country>#{params.items[count].country}</item-country> / <item-label>#{params.items[count].label}</item-label></item-more>
        <item-more><item-format>#{params.items[count].format}</item-format> / <item-number>#{params.items[count].number}</item-number></item-more>
        <item-price>
            <span class="buttons">
                <button class="btn price"><b>#{params.items[count].price}</b> р.</button>
                <button class="btn cart"><span class="glyphicon glyphicon-shopping-cart"></span></button>
            </span>
        </item-price>
    </item-info>
</item>

(Код с подстановкой переменных из coffeescript.)

Загрузка данных

Серверный скрипт (в демо-версии: coverselle-load.php) вызывается с параметрами:

  • object: Внутренний (для дерева html) идентификатор контейнера, в который загружаются обложки. На случай различения нескольких карселей на одной странице.
  • count: Количество обложек для загрузки (соответствует количеству показываемых элементов).
  • token: Генерируемая сервером метка произвольного вида, позволяющая идентифицорвать сессию очереди обложек при перемещении «вперёд/назад» (см. следующий параметр). При запросе следующей (предыдущей) порции обложек передаётся полученный при прошлом запросе идентификатор в неизменном виде. В клиентском скрипте не используется — только сохраняется и передаётся при следущем запросе.
  • go: Указание на то, какую порцию обложек относительно текущего состояния надо загрузить. Возможные значения: next — следующая порция, back — предыдущая порция. Любое иное значние (включая пустое) указывает на первоначальную загрузку данных. (Параметр token в этом случае тоже не будет проинициализирован.)

Скрипт возвращает данные в формате JSON:

    $json = [
        'object' => $object,
        'token' => $token,
        'go' => $go,
        'canGoNext' => $canGoNext,
        'canGoBack' => $canGoBack,
        'items' => $itemsArray
    ];

Параметры object и go сообщают клиентскому скрипту, какой объект получает данные и в каком направлении было перемещение (вперёд или назад). canGoNext и canGoBack (boolean: 0 или пустое значение = false) — указывают, возможно ли перемещение по очереди вперёд или назад соответственно. Если для одного из параметров возвращается пустое (нулевое) значение, соответствующая кнопка перехода («вперёд/назад») становится неактивной.

Элемент списка обложек имеет следующую структуру:

    $itemsArray[$i] = [
        'artist' => 'Artist Name',
        'title' => 'Album Title',
        'country' => 'Country',
        'label' => 'Label',
        'format' => 'Format',
        'number' => 'Number',
        'cover' => 'SamplePix/CoverUrl.jpg',
        'link' => '/Catalogue/LinkUrl/',
        'price' => '3,500'
    ];

Обращаю внимание на то, что цена должна быть преформатирована в общепринятом на сайте формате.

Кроме двух параметров типа «URL» (link — ссылка для перехода по клику на обложке и cover — урл картинки обложки) — все прочие — произвольные текстовые поля.

Основные моменты работы алгоритма загрузки, показа данных и взаимодействия с пользователем

Инициализация

При инициализации объекта карусели и каждом изменении размера страницы происходит расчёт оптимального количества показываемых обложек, — в зависимости от доступного свободного пространства. Расчёт производится из предположения, что обложки должны перекрывать друг друга примерно наполовину. (Серверный скрипт может возвращать обложек меньше, чем затребовано.)

Если объекту .Coverselle не присвоен уникальный идентификатор, то во время инициализации идентификатор создаётся автоматически, — на случай различения нескольких компонентов карусели, расположенных на одной странице.

После этого производится первоначальная загрузка данных (с пустыми значениями параметров 'token' и 'go').

Загрузка

При загрузке данных инициализируется AJAX-запрос к серверному скрипту, которому передаётся серверный идентификатор (token) и направление (go) относительно загруженного ранее набора данных («вперёд/назад»). Скрипт возвращает данные в JSON-формате (см. выше и пример в проекте — coverselle-load.php).

Загруженные данные выкладываются в созданную скрытую секцию (.box.new) в виде корректного HTML (см. выше), после чего одновременно прячется старый набор и показывается новый (если движение вперёд, движение слева направо, если назад, то наоборот).

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

(См. ф-ции loadNext() и placeBox() в coffeescript/javascript коде.)

Демонстрационный скрипт с иллюстративной целью отрабатывает с задержкой в 1 секунду. Точно так же показывается возможность управлять кнопкой «назад» (случайным образом туда передаётся либо 0 либо 1.)

Отработка клика

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

typeof document.documentElement.ontouchstart != 'undefined'

Не знаю, везде ли это будет работать. Проверено на имеющемся в наличии реальном устройстве.

Активация ссылки происходит в том случае, если это сенсорное устройство либо обложка уже показывается в увеличенном размере к.-то время (пока 500мс, полсекунды).

При безусловной обработки клика на сенсорных устройствах нет возможности показать увеличенную обложку с информацией, т.к. в этом случае система совмещает события mouseenter и click.

Т.е., в таких браузерах первый клик увеличивает обложку и показывает детальную информацию, а второй — уже переход по ссылке.



Все исходные файлы в одном архиве: CoverselleSrc.zip (~115K).

См. информацию о проекте boogiemanmusic.

«Лиллипуттен унд Нобле» / Игорь А. Лилипутен <>