Адаптеры

Waypoints — это мощная библиотека для отслеживания прокрутки и выполнения действий, когда элементы появляются в видимой области окна браузера. Ключевой механизм, который делает Waypoints гибким и масштабируемым, — это адаптеры. Они определяют способ взаимодействия Waypoints с DOM и позволяют библиотеке работать с разными средами и фреймворками.

Адаптеры в Waypoints представляют собой объекты, реализующие интерфейс для управления элементами, событиями и размерами окна. Они инкапсулируют логику доступа к DOM, что делает Waypoints независимым от конкретной реализации работы с элементами и событийной модели.


Структура адаптера

Адаптер должен реализовывать следующие методы и свойства:

  1. viewportHeight() — возвращает высоту видимой области окна. Пример реализации для стандартного окна браузера:

    viewportHeight: function() {
        return window.innerHeight || document.documentElement.clientHeight;
    }
  2. scrollY() — возвращает текущее вертикальное смещение прокрутки. Это значение используется для вычисления момента, когда элемент пересекает точку активации Waypoint:

    scrollY: function() {
        return window.pageYOffset || document.documentElement.scrollTop;
    }
  3. offset(element) — возвращает координаты элемента относительно документа. В стандартной реализации используется метод getBoundingClientRect с учётом прокрутки страницы:

    offset: function(element) {
        var rect = element.getBoundingClientRect();
        return {
            top: rect.top + this.scrollY(),
            left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft)
        };
    }
  4. bind(element, event, handler) — привязывает обработчик события к элементу. Позволяет адаптеру использовать нативные события или события библиотеки, такой как jQuery:

    bind: function(element, event, handler) {
        element.addEventListener(event, handler);
    }
  5. unbind(element, event, handler) — удаляет ранее привязанный обработчик события:

    unbind: function(element, event, handler) {
        element.removeEventListener(event, handler);
    }
  6. extend(target, source) — копирует свойства из одного объекта в другой. Часто используется для объединения опций и настроек:

    extend: function(target, source) {
        for (var key in source) {
            if (source.hasOwnProperty(key)) {
                target[key] = source[key];
            }
        }
        return target;
    }

Регистрация адаптера

Waypoints поддерживает регистрацию собственных адаптеров с помощью метода Waypoint.Adapter. Стандартная регистрация выглядит так:

var MyAdapter = {
    viewportHeight: function() { ... },
    scrollY: function() { ... },
    offset: function(element) { ... },
    bind: function(element, event, handler) { ... },
    unbind: function(element, event, handler) { ... },
    extend: function(target, source) { ... }
};

Waypoint.Adapter = MyAdapter;

После регистрации нового адаптера все объекты Waypoints будут использовать его методы для вычислений и управления событиями. Это особенно полезно при интеграции с нестандартными движками или виртуальными DOM-структурами.


Встроенные адаптеры

Waypoints поставляется с несколькими встроенными адаптерами:

  • jQuery Adapter — позволяет использовать библиотеку совместно с jQuery, упрощая доступ к элементам, привязку событий и вычисление смещений. Пример:

    Waypoint.Adapter = {
        viewportHeight: function() { return $(window).height(); },
        scrollY: function() { return $(window).scrollTop(); },
        offset: function(el) { return $(el).offset(); },
        bind: function(el, evt, handler) { $(el).on(evt, handler); },
        unbind: function(el, evt, handler) { $(el).off(evt, handler); },
        extend: $.extend
    };
  • Zepto Adapter — аналогично jQuery, но для лёгкой библиотеки Zepto.

  • Vanilla Adapter — стандартная реализация без сторонних библиотек, работающая на чистом JavaScript.


Создание кастомного адаптера

Кастомные адаптеры позволяют интегрировать Waypoints с фреймворками вроде React, Vue или Svelte, где элементы могут рендериться виртуально. В таких случаях методы offset и bind могут обращаться к виртуальному DOM или использовать специфические события фреймворка.

Пример адаптера для виртуального контейнера:

var VirtualAdapter = {
    viewportHeight: function() { return this.containerHeight; },
    scrollY: function() { return this.scrollTop; },
    offset: function(element) { return this.virtualOffset[element.id] || 0; },
    bind: function(element, event, handler) { this.eventMap[element.id] = handler; },
    unbind: function(element, event, handler) { delete this.eventMap[element.id]; },
    extend: Object.assign
};

Такой подход позволяет Waypoints работать не только с браузерным DOM, но и с любыми структурированными элементами интерфейса.


Практические рекомендации

  • Методы адаптера должны быть максимально производительными, так как они вызываются при каждой прокрутке страницы.
  • В offset важно учитывать любые смещения контейнеров и прокрутки, иначе Waypoints будет срабатывать неверно.
  • При интеграции с библиотеками виртуального DOM следует обеспечить актуальность данных о позициях элементов при каждом ререндере.
  • Использование встроенных адаптеров рекомендуется для стандартных проектов, кастомные адаптеры — для сложных интеграций и SPA-приложений.

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