Обратная совместимость

Библиотека Shopify Draggable построена с учетом современных стандартов JavaScript и возможностей браузеров, однако обеспечение обратной совместимости с более старыми средами является важным аспектом при разработке интерактивных интерфейсов. Обратная совместимость позволяет использовать функционал библиотеки на устройствах с ограниченной поддержкой современных API, минимизируя необходимость внесения изменений в код при обновлениях браузеров или платформ.


Поддержка старых браузеров

Draggable ориентирована на работу с браузерами, поддерживающими ES5, но для полного использования некоторых расширенных возможностей, таких как CustomEvent, classList и Promise, требуется полифиллы. Включение полифиллов обеспечивает:

  • Корректную работу событийных механизмов.
  • Поддержку модулей Drag and Drop на устройствах, не поддерживающих нативные события dragstart, dragend.
  • Возможность использования Sortable и Swappable плагинов без ошибок.

Примеры полифиллов:

// Polyfill для CustomEvent
(function () {
  if (typeof window.CustomEvent === "function") return false;
  function CustomEvent(event, params) {
    params = params || { bubbles: false, cancelable: false, detail: null };
    var evt = document.createEvent("CustomEvent");
    evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
    return evt;
  }
  CustomEvent.prototype = window.Event.prototype;
  window.CustomEvent = CustomEvent;
})();
// Polyfill для classList (IE9+)
if (!("classList" in document.createElement("_"))) {
  Object.defineProperty(HTMLElement.prototype, "classList", {
    get: function () {
      var self = this;
      function update(fn) {
        return function (value) {
          var classes = self.className.split(/\s+/);
          fn(classes, value);
          self.className = classes.join(" ");
        };
      }
      return {
        add: update(function (classes, value) { if (!classes.includes(value)) classes.push(value); }),
        remove: update(function (classes, value) { var index = classes.indexOf(value); if (index !== -1) classes.splice(index, 1); }),
        toggle: update(function (classes, value) { if (classes.includes(value)) classes.splice(classes.indexOf(value), 1); else classes.push(value); }),
        contains: function (value) { return self.className.split(/\s+/).includes(value); }
      };
    }
  });
}

Работа с событиями в старых средах

Draggable полагается на CustomEvent для передачи информации о начале и завершении перетаскивания, перемещении элемента, обмене местами и других интеракциях. В старых браузерах необходимо учитывать:

  1. Отсутствие поддержки event.preventDefault() для некоторых встроенных событий.
  2. Некорректную работу MouseEvent и TouchEvent в IE11 и старых версиях Safari.
  3. Необходимость ручной привязки событий с использованием attachEvent вместо addEventListener в Internet Explorer до версии 9.

Для обеспечения совместимости можно использовать вспомогательные функции:

function addEventCompat(el, type, handler) {
  if (el.addEventListener) {
    el.addEventListener(type, handler, false);
  } else if (el.attachEvent) {
    el.attachEvent('on' + type, function() {
      handler.call(el, window.event);
    });
  }
}

Полифиллы для анимации и трансформаций

Draggable использует CSS трансформации для плавного перемещения элементов. В старых браузерах требуется проверка наличия префиксов -webkit-, -ms- и -moz-. Для обратной совместимости:

  • Свойство transform заменяется на -webkit-transform для старых версий Safari и Chrome.
  • requestAnimationFrame полифилится для последовательного обновления позиций без сильной нагрузки на CPU:
window.requestAnimationFrame = window.requestAnimationFrame ||
                               window.webkitRequestAnimationFrame ||
                               window.mozRequestAnimationFrame ||
                               function(callback){ return setTimeout(callback, 16); };
  • Если CSS-переходы недоступны, допускается fallback на прямое изменение top и left.

Обработка сенсорных устройств

Draggable поддерживает Touch API, но старые мобильные браузеры могут не распознавать события touchstart, touchmove и touchend корректно. Для обратной совместимости:

  • Использовать объединение pointer events и touch events.
  • Реализовать fallback на mousedown, mousemove, mouseup при отсутствии Touch API.
var startEvent = 'ontouchstart' in window ? 'touchstart' : 'mousedown';
var moveEvent = 'ontouchmove' in window ? 'touchmove' : 'mousemove';
var endEvent = 'ontouchend' in window ? 'touchend' : 'mouseup';

Поддержка модулей Draggable

Draggable включает плагины Sortable, Swappable и Droppable. Для старых браузеров:

  • Проверять поддержку ES6 классов и модулей.
  • При необходимости подключать сборку библиотеки в формате UMD, совместимую с CommonJS и AMD.
  • Использовать транспайлеры, такие как Babel, чтобы преобразовать код ES6+ в ES5 для старых сред.
// Пример подключения Draggable через UMD
<script src="https://cdn.jsdelivr.net/npm/@shopify/draggable/lib/draggable.bundle.legacy.js"></script>

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

  • Всегда проверять поддержку браузеров целевой аудитории перед использованием расширенных функций.
  • Для обеспечения плавного обновления интерфейса использовать requestAnimationFrame даже в старых браузерах.
  • Подключать полифиллы заранее, чтобы события Draggable работали корректно.
  • Обновлять сборки библиотеки, сохраняя UMD-версию для старых проектов, которые не используют модульные сборки.

Обратная совместимость в Draggable обеспечивает стабильность интерактивных интерфейсов на множестве устройств и браузеров, минимизируя зависимость от новейших возможностей JavaScript и CSS, что критично для проектов с долгим жизненным циклом.