isContainer - функция определения контейнеров

В библиотеке Dragula для организации перетаскивания элементов между блоками ключевым компонентом является функция isContainer. Она отвечает за определение, какие DOM-элементы могут выступать в качестве контейнеров для draggable-элементов. Понимание её работы позволяет гибко управлять логикой перетаскивания и ограничивать действия пользователя строго заданными зонами.


Основы работы функции

По умолчанию Dragula рассматривает каждый контейнер как допустимую область для перемещения элементов. Контейнеры передаются в Dragula через массив в параметре containers. Однако для более тонкой настройки используется опциональная функция isContainer. Она проверяет каждый потенциальный контейнер и возвращает логическое значение:

const drake = dragula({
    isContainer: function (el) {
        return el.classList.contains('drag-container');
    }
});

Ключевой момент: функция вызывается с аргументом el, который представляет собой DOM-элемент. Если функция возвращает true, этот элемент считается контейнером; если false — игнорируется библиотекой при перетаскивании.


Использование с динамическими элементами

В реальных приложениях контейнеры могут создаваться динамически. Функция isContainer позволяет проверять элементы в момент их добавления в DOM:

const drake = dragula({
    isContainer: function (el) {
        return el.tagName === 'DIV' && el.dataset.drag === 'true';
    }
});

В данном примере контейнером становится только <div> с атрибутом data-drag="true". Это предотвращает случайное перетаскивание в неподходящие блоки и обеспечивает высокую гибкость для динамически изменяемых интерфейсов.


Совместимость с другими настройками Dragula

Функция isContainer взаимодействует с другими опциями, такими как:

  • moves(el, source, handle, sibling) — определяет, какие элементы могут быть перемещены. Использование isContainer в сочетании с moves позволяет полностью контролировать как контейнеры, так и перетаскиваемые элементы.
  • accepts(el, target, source, sibling) — проверяет, можно ли разместить элемент в целевом контейнере. Даже если isContainer вернет true, accepts может запретить перемещение элемента.

Пример комбинированного использования:

const drake = dragula({
    isContainer: function (el) {
        return el.classList.contains('drop-zone');
    },
    moves: function (el, source, handle, sibling) {
        return el.classList.contains('draggable-item');
    },
    accepts: function (el, target, source, sibling) {
        return target.classList.contains('drop-zone') && !target.classList.contains('full');
    }
});

Поддержка вложенных контейнеров

Dragula позволяет работать с вложенными контейнерами, если isContainer корректно идентифицирует все уровни вложенности:

const drake = dragula({
    isContainer: function (el) {
        return el.classList.contains('nested-container');
    }
});

В таком случае элементы можно перемещать как на верхнем уровне, так и внутри вложенных зон, соблюдая правила accepts и moves. Важно, чтобы функция isContainer корректно возвращала true только для допустимых контейнеров — иначе вложенные элементы могут некорректно обрабатывать события drag-and-drop.


Производительность и оптимизация

Для приложений с большим количеством элементов использование isContainer позволяет:

  • Избежать лишней проверки всех элементов DOM.
  • Ограничить область поиска контейнеров до реально нужных блоков.
  • Обеспечить более отзывчивое поведение при drag-and-drop, особенно на мобильных устройствах.

Рекомендуется избегать сложных вычислений внутри isContainer. Например, проверка через querySelectorAll на каждом вызове может замедлить интерфейс при большом числе элементов. Лучше использовать простые проверки класса, атрибута или типа элемента.


Примеры практических сценариев

  1. Только определённые секции интерфейса как контейнеры:
const drake = dragula({
    isContainer: function (el) {
        return el.id.startsWith('section-');
    }
});
  1. Контейнеры с несколькими условиями:
const drake = dragula({
    isContainer: function (el) {
        return el.classList.contains('drop-zone') && el.dataset.active === 'true';
    }
});
  1. Запрет контейнеров для определённых элементов:
const drake = dragula({
    isContainer: function (el) {
        return !el.classList.contains('locked-container');
    }
});

Использование isContainer является фундаментальным инструментом Dragula для создания управляемых и безопасных зон перетаскивания. Она обеспечивает точную фильтрацию контейнеров, позволяет поддерживать динамический DOM и интегрируется с другими методами контроля перетаскивания, создавая гибкую и производительную систему drag-and-drop.