Плагин jQuery.Snapper предназначен для управления размещением и перемещением панелей на странице. Основные отличия от аналогичных плагинов:

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

Загрузить jQuery.Snapper

Описание Рабочая версия Версия для отладки
Управление размещением и перемещением панелей jquery.snapper.min.js jquery.snapper.js
Сохранение размещения панелей в кэше браузера jquery.snapper.storage.min.js jquery.snapper.storage.js
Ввода пальцами для IE10 с поддержкой скроллинга jquery.mspointer.min.js jquery.mspointer.js

Загрузить одним файлом

Как это работает

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

Зависимости

Единственная обязательная зависимость - jQuery. На мобильных устройства для плавной анимации опционально можно добавить jQuery.Transit - замена animate на transition. При необходимости изменения функции инерционной анимации можно добавить библиотеку jQuery.Easing.

Подключение плагина

Для использования необходимо включить библиотеку jQuery.Snapper на страницу, содержащую контейнеры. Привязка плагина к контейнеру производится путем маркировки атрибутом data-toggle="snapper" или через вызов метода инициализации плагина $('.container').snapper().

Панель 1
Для перемещения нажмите и подержите кнопку мыши
Панель 2
Для перемещения нажмите и подержите кнопку мыши
Панель 3
Для перемещения нажмите и подержите кнопку мыши
<!-- Библиотека с плагином -->
<script src="js/libs/jquery.snapper.min.js"></script>
...
<!-- Контейнер с плагином -->
<div class="container" data-toggle="snapper">
    <div class="panel">...</div>
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>

Несколько контейнеров

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

Панель 1
Перенести вверх, вниз, влево, вправо
Панель 2
Перенести вверх, вниз, влево, вправо
Панель 3
Перенести вверх, вниз, влево, вправо
Панель 4
Перенести вверх, вниз, влево, вправо
Панель 5
Перенести вверх, вниз, влево, вправо
Панель 6
Перенести вверх, вниз, влево, вправо
<!-- Верхний контейнер -->
<div class="container top" data-toggle="snapper">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>
<!-- Левый контейнер -->
<div class="container left" data-toggle="snapper">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>
<!-- Правый контейнер -->
<div class="container right" data-toggle="snapper">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>

Пример 1. Несколько контейнеров

Запрет выхода из контейнера

По умолчанию панель, брошенная за переделы контейнера будет удалена из DOM-модели или захвачен другим контейнером. Для запрета удаления панелей из контейнера установите data-out="cancel". Перемещение панелей становится возможно только внутри контейнера. Такой контейнер также не будет захватывать панели других контейнеров.

Панели можно переставлять только внутри этого контейнера

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

Панель 1
Только вверх/вниз
Панель 2
Только вверх/вниз
Панель 3
Только вверх/вниз
Панель 1
Сбрось меня вправо
Панель 2
Сбрось меня вправо
Панель 3
Сбрось меня вправо
<!-- Перемещение панелей только внутри контейнера -->
<div class="container" data-toggle="snapper" data-out="cancel">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>

<!-- Перемещение и удалений панелей из контейнера -->
<div class="container" data-toggle="snapper" data-out="remove">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>

Обмен панелями

Если все же необходимо чтобы панели могли переходить на другой контейнер при этом количество панелей на каждом контейнере оставалось неизменными применяется. атрибут data-out="swap"

При переносе контейнеры обмениваются панелями

Панель 1
Обменяй меня на соседнюю
Панель 2
Обменяй меня на соседнюю
Панель 3
Обменяй меня на соседнюю
Панель 1
Обменяй меня на соседнюю
Панель 2
Обменяй меня на соседнюю
Панель 3
Обменяй меня на соседнюю
<!-- Перемещение и удалений панелей из контейнера -->
<div class="container" data-toggle="snapper" data-out="swap">
    <div class="panel">...</div>
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>

<!-- Перемещение панелей только внутри контейнера -->
<div class="container" data-toggle="snapper" data-out="swap">
    <div class="panel">...</div>
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>

Ловушки для панелей

При сложной верстке может потребоваться размешение панелей в различных местах странице по разными контейнерам. При этом часто возникает необходимость предотварить возможность выхода элемента за пределы экрана и удаление. С этой целью на одном или нескольких контейнерах можно включить ловушки, установив атрибут data-catch="...". Атрибут может принимать одно или несколько значений из набора top right bottom left. Указание направления отменяет проверку соответствующей координаты контейнера для определения территории захвата.

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

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

Панель 1
Брось меня вниз или вправо
Панель 2
Брось меня вниз или вправо
Панель 3
Брось меня вниз или влево
Панель 4
Брось меня вниз или влево
<!-- Ловушка слева -->
<div class="container left" data-toggle="snapper" data-catch="left">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>
<!-- Ловушка справа -->
<div class="container right" data-toggle="snapper" data-catch="right">
    <div class="panel">...</div>
    <div class="panel">...</div>
</div>
<!-- Ловушка снизу и по сторонам для надежности -->
<div class="container bottom" data-toggle="snapper" data-catch="bottom left right">
</div>

Обработка событий

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

  • Отрыв панели от контейнера и начало перетаскивания drag
  • Бросание панели в позиции с учетом инерции движения drop
  • Завершение захвата панели (создает контейнер приемник) snap
  • Завершение перемещения/удаления панели (создает контейнер источник) done
<script>
    $(function() {
        <!-- Обработка события завершения перемещения -->
        $(document).on('done.snapper', '.container', function() {
            $.waypoints('refresh');
        });
        $('.panel').css('opacity', 0);
        $('.panel').waypoint(function(direction) {
            $(this).animate({opacity: direction === 'down' ? 1 : 0}, 400);
        }, {offset: '90%'});    
</script>

Пример 2. Обработка событий

Сохранение состояний

Для добавления сохранения размещения панелий на странице достаточно включить добавить библиотеку jQuery.Snapper.Storage.

Идентификация контейнеров и панелей производится по id элемента. Если не задано присваивается автоматически в порядке размещения на странице. С точки зрения будущих изменений/обновлений страницы рекомендую добавлять id на каждый элемент.

Если в дальнейшем изменяется начальный состав панелей в контейнере, например добавляется новая панель, чтобы корректно обновить страницу пользователя достаточно включить в идентификатор id номер версии контейнера. Существующие перемещенные элементы в этом случае у пользователя займут свои места, а новые элементы будут отражены в контейнера новой версии.

<!-- Библиотека с плагином -->
<script src="js/libs/jquery.snapper.min.js"></script>
<!-- Библиотека сохранения состояний -->
<script src="js/libs/jquery.snapper.storage.min.js"></script>
...
<!-- Размещение панелей сохраняется в кэше браузера -->
<div id="block_1" class="container" data-toggle="snapper">
    <div id="item_1" class="panel">...</div>
    <div id="item_2" class="panel">...</div>
    <div id="item_3" class="panel">...</div>
</div>

Пример 3. Сохранение состояний

Стилевое оформление

Панель в процессе перемещения привязана к document.body. Стиль можно задать через привязку к родителю. Таким образом, например, можно задать эффект "отлипания" панели от контейнера.

<!-- Панель приподнимается над контейнером -->
body > .panel {
    -moz-box-shadow: 0 0 15px #555;
    -webkit-box-shadow: 0 0 15px #555;
    box-shadow: 0 0 15px #555;
    border: outset 1px #f0f0f0;
    transition: border, box-shadow ease-in 200ms;
    -webkit-transition: border, -webkit-box-shadow ease-in 200ms;
    -moz-transition: border, -moz-box-shadow ease-in 200ms;
}

Управление пальцами в IE10

Для управления размещением панелей пальцами в IE10 требуется указать параметр -ms-touch-action: none. Но в этом случае исчезает возможность пальцем осуществлять плавный скроллинг. В FF и WebKit блокировка системного скроллинга может быть осуществлена непосредственно из обработчика событий. Напротив в IE10 параметр -ms-touch-action: none начинает работать только после окончания касания экрана.

Для совмещения функции системного скроллинга в IE10 и работы плагина используется библиотека jQuery.MSPointer, которая для IE10 подменяет мышиные события MouseEvent на события MSPointerEvent, что позволяет различать ввод мышью/пальцами/пером. В этом случае особенностью работы пальцами/пером в IE10 при сохранении скроллинга становиться необходимость повторного касания экрана для перемещения панели при временно отключенном системном скроллинге.

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

<!-- Подмена мышиных событий в IE10 -->
<script src="js/libs/jquery.mspointer.min.js"></script>
<!-- Библиотека с плагином -->
<script src="js/libs/jquery.snapper.min.js"></script>
...
<!-- Для IE10 здесь будет работать системный скроллинг и перемещение панелей пальцами -->
<div id="block_1" class="container" data-toggle="snapper">
    <div id="item_1" class="panel">...</div>
    <div id="item_2" class="panel">...</div>
    <div id="item_3" class="panel">...</div>
</div>