Модуль UI Sortable — сортировка элементов

Модуль UI Sortable позволяет сортировать элементы с помощью мыши. Для загрузки модуля переходим на страницу http://jqueryui.com/download. Оставляем установленными флажки UI Core, Draggable, Sortable, 1.7.2, а затем щелкаем на кнопке Download. Распаковываем архив в отдельную папку. Из этого архива для работы модуля необходимы следующие файлы:

Все указанные файлы необходимо подключить к скрипту в том порядке, в котором они перечислены. В качестве примера рассмотрим функциональные возможности модуля с параметрами, принятыми по умолчанию, а также применение опции connectToSortable (листинг 12.7).

Листинг 12.7. Модуль UI Sortable, сортировка элементов списка

<!doctype html>
<html>
<head>
<title>Модуль UI Sortable. Сортировка элементов списка</title>
<meta charset="utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery-ui-1.7.2.custom.min.js"></script>
<style>
body { font-size:10pt; font-family:Verdana, sans-serif; }
ul { margin:0; padding:0; list-style-type:none; }
li { margin: 0 3px 3px 20px; padding: 5px 5px 5px 20px;
     width:200px; height:18px;
     font-size:16px; font-family:Verdana, sans-serif;
     border: 1px solid #000000; color:#000000; font-weight:bold; }
.itemColor1 { background-color:#fff4dd; }
.itemColor2 { background-color:#d5dee7; }
</style>
<script>
$(document).ready(function() {
   $("#sortable").sortable().disableSelection();
   $("#draggable li").draggable({
      helper: "clone", // Перемещение копии элемента
      // Пункты можно добавить в список с id=sortable
      connectToSortable: "#sortable"
   }).disableSelection(); // Запрещаем выделение текста пунктов
});
</script>
</head>
<body>
<span style="font-weight:bold;">Сортируемый список</span><br><br>
<ul id="sortable">
<li class="itemColor1">Пункт 1</li>
<li class="itemColor1">Пункт 2</li>
<li class="itemColor1">Пункт 3</li>
<li class="itemColor1">Пункт 4</li>
</ul><br><br>
<span style="font-weight:bold;">Из этого списка можно добавить пункты
в сортируемый список</span><br><br>
<ul id="draggable">
<li class="itemColor2">Пункт 1</li>
<li class="itemColor2">Пункт 2</li>
<li class="itemColor2">Пункт 3</li>
<li class="itemColor2">Пункт 4</li>
</ul>
</body>
</html>

Для того чтобы элементы можно было сортировать с помощью мыши, необходимо применить метод sortable(). Формат метода:

sortable([<Объект с опциями>])

Параметр <Объект с опциями> представляет собой объект, состоящий из пар "опция/значение". Могут быть указаны следующие опции.

Значение по умолчанию — false.

Значение по умолчанию — false (при перемещении элемента курсор располагается в том месте, где был произведен щелчок мышью).

Рассмотрим несколько примеров. Во время перемещения курсор будет находится над верхней границей элемента.

cursorAt: { top: 0 }

Курсор будет расположен в левом верхнем углу.

cursorAt: { top: 0, left: 0 }

Курсор будет расположен на одном уровне с верхней границей, но сдвинут на 5 px от элемента относительно правой границы.

cursorAt: { top: 0, right: -5 }

Курсор будет смещен на 5 px ниже нижней границы и на 5 px от левой границы элемента.

cursorAt: { bottom: -5, left: -5 }

Обратите внимание

Нельзя одновременно указывать свойства top и bottom, а также left и right.

[<Шаг по горизонтали>, <Шаг по вертикали>]

Рассмотрим пример.

grid: [40, 20]

Значение по умолчанию — false.

В качестве значения может быть указана ссылка на функцию. В этом случае функция должна возвращать DOM-элемент.

<ul id="sortable">
<li class="itemColor">Пункт 1</li>
<li class="itemColor">Пункт 2</li>
</ul>

В начале перемещения второго пункта исходный HTML-код списка будет выглядеть следующим образом.

<ul id="sortable" class="ui-sortable" unselectable="on">
<li class="itemColor">Пункт 1</li>
<li class="itemColor" style="width:200px;height:18px;
    position:absolute;z-index:1000">Пункт 2</li>
<li class="itemColor ui-sortable-placeholder"
    style="visibility:hidden"></li>
</ul>

Как видно из примера, перемещаемый элемент получает абсолютное позиционирование, а на его место вставляется скрытая "заглушка".

<li class="itemColor ui-sortable-placeholder"
    style="visibility:hidden"></li>

Если в опции placeholder указан стилевой класс (например, cls1), то исходный код "заглушки" будет выглядеть так.

<li class="cls1"></li>
placeholder: "cls1",
forcePlaceholderSize: true

исходный код "заглушки" будет выглядеть так.

<li class="cls1" style="height:18px"></li>

Значение по умолчанию — false.

Пример создания сортируемых списков с различными вариантами параметров настройки приведен в листинге 12.8.

Листинг 12.8. Модуль UI Sortable, различные варианты параметров настройки

<!doctype html>
<html>
<head>
<title>Модуль UI Sortable. Различные варианты настроек</title>
<meta charset="utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery-ui-1.7.2.custom.min.js"></script>
<style>
body { font-size:10pt; font-family:Verdana, sans-serif; }
ul { margin:0; padding:0; list-style-type:none; }
li { margin: 0 3px 3px 20px; padding: 5px 5px 5px 20px;
     width:200px; height:18px;
     font-size:16px; font-family:Verdana, sans-serif;
     border: 1px solid #000000; color:#000000; font-weight:bold;
}
.itemColor1 { background-color:#fff4dd; }
.itemColor2 { background-color:#d5dee7; }
.cls1 { border: dotted 1px black; background-color:#ffe9b3; }
</style>
<script>
$(document).ready(function() {
   $("#sortable1").sortable({
      items: "li", // Перемещаем элементы LI
      axis: "y", // Перемещение только по вертикали
      cursor: "s-resize", // Вид курсора при перемещении
      cancel: "span", // За элемент SPAN переместить нельзя
      // Куда можно переместить
      connectWith: "#sortable2,#sortable3",
      delay: 200 // Задержка перед перемещением
   }).disableSelection();
   $("#sortable2").sortable({
      revert: true, // Перемещение с анимацией
      containment: "window", // Перемещение в пределах окна
      opacity: 0.5, // Степень прозрачности
      helper: "clone", // Перемещение копии пункта списка
      placeholder: "cls1", // Класс для "заглушки"
      // Куда можно переместить
      connectWith: "#sortable1,#sortable3",
      // Добавить элементы в пустой список нельзя
      dropOnEmpty: false,
      cursorAt: { top: 0 } // Перемещение за верхнюю границу
   }).disableSelection();
   $("#sortable3").sortable({
      // Куда можно переместить
      connectWith: "#sortable1,#sortable2"
   }).disableSelection();
});
</script>
</head>
<body>
<span style="font-weight:bold;">Сортируемый список 1</span><br>
За красный прямоугольник переместить элемент нельзя<br><br>
<ul id="sortable1">
<li class="itemColor1">Пункт 1
<span style="background-color:red;">&nbsp;&nbsp;&nbsp;&nbsp;</span>
</li>
<li class="itemColor1">Пункт 2</li>
<li class="itemColor1">Пункт 3</li>
<li class="itemColor1">Пункт 4</li>
</ul><br><br>
<span style="font-weight:bold;">Сортируемый список 2</span><br><br>
<ul id="sortable2">
<li class="itemColor2">Пункт 1</li>
<li class="itemColor2">Пункт 2</li>
<li class="itemColor2">Пункт 3</li>
<li class="itemColor2">Пункт 4</li>
</ul><br><br>
<span style="font-weight:bold;">Сортируемый список 3</span><br>
Добавить элементы в этот пустой список можно только
из списка 1<br><br>
<ul style="background-color:#fff4dd;margin:5px;padding:5px;width:250px;"
id="sortable3">
</ul>
</body>
</html>

Чтобы изменить или получить значения опций уже после создания, необходимо использовать второй формат метода sortable(). Для этого в первом параметре указывается значение "option", во втором — название опции, а в третьем — новое значение.

$("#sortable").sortable("option", "delay", "200");

Если необходимо получить значение опции, то третий параметр указывать не нужно. В качестве примера получим значение опции delay.

alert($("#sortable").sortable("option", "delay"));

Второй формат метода sortable() позволяет также управлять элементом. Для этого в первом параметре указываются следующие значения.

sortable("serialize"[, <Объект с опциями>])

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

<Название>_<Число>

Например:

id="item_1"

В качестве разделителя, вместо символа подчеркивания, можно использовать знак равенства (=) или дефис (-). Если идентификаторы равны item_1, item_2, item_3, то в результате получим следующую строку.

item[]=1&item[]=2&item[]=3

В параметре <Объект с опциями> можно дополнительно указать объект со следующими свойствами.

Рассмотрим пример использования параметра <Объект с опциями>.

$("#sortable").sortable("serialize", {
   attribute: "id",
   key: "myParam[]",
   expression: /_(.+)/
});

Если идентификаторы равны item_1, item_2, item_3, то в результате получим следующую строку.

myParam[]=1&myParam[]=2&myParam[]=3
sortable("toArray"[, <Объект с опциями>])

Если идентификаторы равны item_1, item_2, item_3, то в результате выполнения кода

var arr = $("#sortable").sortable("toArray");
var msg = "";
for (var i=0, j=arr.length; i<j; i++)
   msg += "[" + i + "] => " + arr[i] + "\n";
alert(msg);

получим следующий массив.

[0] => item_1
[1] => item_2
[2] => item_3

В параметре <Объект с опциями> с помощью свойства attribute можно указать атрибут тега, значения которого необходимо вернуть.

var arr = $("#sortable").sortable("toArray", {attribute: "id"});

Обработать события, происходящие с сортируемым списком, можно двумя способами.

sortable({
   <Событие>: <Функция обратного вызова>
});

или

bind(<Событие>, <Функция обратного вызова>)

В параметре <Событие> могут быть указаны следующие события (в скобках указано значение для метода bind()).

В параметре <Функция обратного вызова> указывается ссылка на функцию следующего формата.

function <Название функции>([<Объект event>[, <Объект UI>]]) {
   // ...
}

Через параметр <Объект UI> доступны следующие свойства.

Пример обработки различных событий приведен в листинге 12.9.

Листинг 12.9. Модуль UI Sortable, обработка событий

<!doctype html>
<html>
<head>
<title>Модуль UI Sortable. Обработка событий</title>
<meta charset="utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery-ui-1.7.2.custom.min.js"></script>
<style>
div { margin: 0; padding: 0; }
body { font-size:10pt; font-family:Verdana, sans-serif; }
h2 { background-color: #ffe9b3; font-size: 12pt;
   padding: 3px 3px 3px 10px; margin: 0 0 5px 0;
}
.section {
   margin: 0 0 15px 5px; width: 300px; height: 100px;
   background-color: #fffbef; border: 1px solid #000000;
   color: #000000; font-weight: bold;
}
#sections, #sections2 { width: 400px; }
</style>
<script>
$(document).ready(function() {
   $("#sections").sortable({
      items: "div", // Сортируемые элементы
      handle: "h2", // Перемещение только за заголовок
      revert: true, // Перемещение с анимацией
      connectWith: "#sections2", // Куда можно переместить
      start: function(e, ui) {
         $("#div1").html("Событие start<br>");
         ui.helper.find("h2").css("background-color", "#ff0000");
      },
      sort: function() { $("#div1").append("Событие sort<br>"); },
      change: function() { $("#div1").append("Событие change<br>"); },
      beforeStop: function(e, ui) {
         $("#div1").append("Событие beforeStop<br>");
         ui.helper.find("h2").css("background-color", "#ffe9b3");
      },
      stop: function() {$("#div1").append("Событие stop<br>"); },
      update: function() { $("#div1").append("Событие update<br>"); },
      receive: function(e, ui) {
         $("#div1").append("Событие receive<br>");
         ui.item.find("p")
           .html("Элемент перемещен из другого списка");
      },
      remove: function() { $("#div1").append("Событие remove<br>"); },
      over: function() { $("#div1").append("Событие over<br>"); },
      out: function() { $("#div1").append("Событие out<br>"); },
      activate: function() {
         $("#div1").append("Событие activate<br>");
      },
      deactivate: function() {
         $("#div1").append("Событие deactivate<br>");
      }
   });
   $("#sections2").sortable({
      items: "div", // Сортируемые элементы
      handle: "h2", // Перемещение только за заголовок
      connectWith: "#sections" // Куда можно переместить
   });
   $("#btn1").click(function() {
      $("#sections").sortable("disable");
   });
   $("#btn2").click(function() {
      $("#sections").sortable("enable");
   });
   $("#btn3").click(function() {
      $("#sections").sortable("cancel");
   });
   $("#btn4").click(function() {
      alert($("#sections").sortable("serialize", { attribute: "id",
         key: "myParam[]", expression: /_(.+)/ }));
      var arr = $("#sections").sortable("toArray",
                                        { attribute: "id" });
      var msg = "";
      for (var i=0, count=arr.length; i<count; i++)
         msg += "[" + i + "] => " + arr[i] + "\n";
      alert(msg);
   });
});
</script>
</head>
<body>
<input type="button" value="Запретить" id="btn1">
<input type="button" value="Разрешить" id="btn2">
<input type="button" value="Отменить сортировку списка 1" id="btn3">
<input type="button" value="Положение элементов списка 1" id="btn4">
<br><br>
Переместить элементы можно только за заголовок<br><br>
<table border="0"><tr><td valign="top">
<div id="sections">
<div class="section" id="item_1">
<h2>Секция 1</h2><p> Содержимое секции 1</p></div>
<div class="section" id="item_2">
<h2>Секция 2</h2><p> Содержимое секции 2</p></div>
<div class="section" id="item_3">
<h2>Секция 3</h2><p> Содержимое секции 3</p></div>
</div>
</td><td valign="top">
<div id="sections2">
<div class="section" id="item_4">
<h2>Секция 4</h2><p> Содержимое секции 4</p></div>
<div class="section" id="item_5">
<h2>Секция 5</h2><p> Содержимое секции 5</p></div>
<div class="section" id="item_6">
<h2>Секция 6</h2><p> Содержимое секции 6</p></div>
</div></td><td valign="top">
<div id="div1"></div>
</td></tr></table>
</body>
</html>
Предыдущая статья Все статьи Следующая статья