JS/jQuery

jQuery UI Sortable - перетаскивание элементов

Перетаскивание элементов мышью это удобный прием для задания сортировки списков, таблиц, блоков и т.д. Самый простой способ это реализовать – использование плагина jQuery UI Sortable.

Параметры и события плагина можно посмотреть на http://api.jqueryui.com/sortable/.

1

Перетаскивание списков

Нужно только подключить файлы скриптов jQuery, jQuery UI и вызвать плагин с селектором списка <ul>.

<ul class="sortable-ul">
    <li class="bg-yellow">Строка 1</li>
    <li class="bg-yellow">Строка 2</li>
    <li class="bg-green">Строка 3</li>
    <li class="bg-green">Строка 4</li>
    <li class="bg-purple">Строка 5</li>
    <li class="bg-purple">Строка 6</li>
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

<script>
$('.sortable-ul').sortable();
</script>

Перетаскивание за определенный элемент

Если в списке нужно будет выделять и копировать текст, например в текстовых полях, то перемещение за всю область сделает это проблематичным. Поэтому делают перемещение кликнув по иконке, так можно сделать добавив параметр handle и указав в нем название ее класса.

<ul class="sortable-ul">
    <li>
        <i class="handle"></i> 
        Строка 1 
        <input type="text" placeholder="Введите текст">
    </li>
    ...
</ul>

<script>
$('.sortable-ul').sortable({
    handle: '.handle'
});
</script>
<ul class="sortable-ul">
    <li>Строка 1</li>
    <li class="disabled">Строка 2</li>
    ...
</ul>

<style>
.disabled {
    opacity: 0.5;
}
</style>

<script>
$('.sortable-ul').sortable({
    cancel: '.disabled'
});
</script>

Добавить анимацию

В параметре revert указывается скорость анимации в миллисекундах, она появляется после отпускания элемента.

$('.sortable-ul').sortable({
    revert: 100
});

Многоуровневые списки

Если нужно сделать сортируемый многоуровневый список, то достаточно в вызове плагина указать кроме основного и вложенные <ul>.

<ul class="sortable-ul">
    <li><div>Строка 1</div></li>
    <li>
        <div>Строка 2</div>
        <ul>
            <li><div>Строка 2.1</div></li>
            <li><div>Строка 2.2</div></li>
            <li><div>Строка 2.3</div></li>
            <li><div>Строка 2.4</div></li>
        </ul>        
    </li>
    <li><div>Строка 3</div></li>
    <li><div>Строка 4</div></li>
</ul>

<script>
$('.sortable-ul, .sortable-ul li > ul').sortable();
</script>
2

Перетаскивание плиток и панелей

Плагин также работает с плавающими элементами float: left.

<div class="sortable-img">
    <div><img src="/demo/1-min.jpg" alt=""></div>
    <div><img src="/demo/2-min.jpg" alt=""></div>
    ...
</div>

<script>
 $('.sortable-img').sortable();
</script>

<style>
.sortable-img div {
    margin: 0 10px 10px 0;
    float: left;
}
</style>

Плагин удобно использовать в настраиваемых фильтрах:

3

Перетаскивание строк таблицы

UI Sortable в основном ориентирован на списки, у таблиц нужен небольшой фикс т.к. при перетаскивании строки, ее ширина становится меньше чем сама таблица.

var fixHelper = function(e, ui) {
    ui.children().each(function() {
        $(this).width($(this).width());
    });
    return ui;
};    

$('.sortable-table tbody').sortable({
    helper: fixHelper
});
4

Как сохранить порядок

Вариант на AJAX и PHP

Список выводится из базы данных отсортированный по полю `sort` (INT 11). В каждом элементе списка находится input[type=hidden] с названием sort[] и содержащий id записи.

После изменения порядка вызывается метод stop, в котором все input hidden отправляются через POST AJAX на save.php.

<?php
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');
$sth = $dbh->prepare("SELECT * FROM `table` ORDER BY `sort`");
$sth->execute();
$array = $sth->fetchAll(PDO::FETCH_ASSOC);
?>

<ul class="sortable-ul">
    <?php foreach ($array as $row): ?>
    <li>
        <?php echo $row['name']; ?>
        <input type="hidden" name="sort[]" value="<?php echo $row['id']; ?>">
    </li>
    <?php endforeach; ?>
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

<script>
$('.sortable-ul').sortable({
    stop: function() {
        $.ajax({
            url: '/save.php',
            method: 'post',
            data: $('.sortable-ul input').serialize()
        });
    }
});
</script>

Код файла save.php:

Скрипт в цикле перебирает массив $_POST['sort'] и обновляет в БД поле `sort` у нужных записей и в нужном порядке.

<?php
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');

if (!empty($_POST['sort'])) {
    foreach ($_POST['sort'] as $i => $row) {
        $sth = $dbh->prepare("UPDATE `table` SET `sort` = :sort WHERE `id` = :id");
        $sth->execute(array('sort' => ++$i, 'id' => intval($row)));
    }
}

Вариант на cookies

У каждого <li> добавлен атрибут data-id с порядковым номером. После перетаскивания значения из data-id собираются в массив и сохраняется в cookies в виде строки JSON, а при обновлении страницы порядок восстанавливается из них.

Для упрощения работы с cookie используется плагин jQuery Cookie.

<ul class="sortable-ul">
    <li data-id="1">Строка 1</li>
    <li data-id="2">Строка 2</li>
    ...
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="/demo/jquery.cookie.min.js"></script>

<script>
// Если есть запись в cookie, то восстанавливаем порядок.
if ($.cookie('sort')) {     
    $.each(JSON.parse($.cookie('sort')), function(i, row){
        $('.sortable-ul').append($('.sortable-ul li[data-id=' + row + ']'));
    });
}

$('.sortable-ul').sortable({
    stop: function() {
        // Собираем все data-id в массив.
        var sort = [];
        $('.sortable-ul li').each(function(){
            sort.push($(this).data('id'));
        });

        // И сохраняем его в cookie в виде строки JSON.    
        $.cookie('sort', JSON.stringify(sort));
    }
});
</script>
23 ноября 2017