Внимание! Эта статья устарела. Новая статья по этой теме: «jQuery UI – плагин Droppable«. Библиотека jQuery предоставляет возможность не только легко и просто написать код, который позволит свободно перемещать элементы по странице. В ее состав, вернее в состав ее расширений входит функция droppable, которая позволяет также довольно просто написать код, который будет обрабатывать события, которые происходят в момент окончания перемещения элемента.
Что полезного с практической точки зрения можно сделать, воспользовавшись такой возможностью. Первое, что приходит в голову – это какая-нибудь интерактивная корзина для интернет-магазина. Вот и попробуем сделать такой пример.
Как всегда сначала попробуем испытать готовый пример, а затем разберемся как работает этот код. Берем мышкой нужный продукт и тащим его в корзину. Над корзиной отпускаем и смотрим, что получилось…
Чтобы не усложнять код примера, не применяются некоторые проверки, которые должны быть использованы в целях безопасности в реальных интернет-магазинах.
Вы можете сохранить исходный код примера и при наличии у Вас библиотеки jQuery, воспроизвести его на своем сайте.
Чтобы все это работало, нам потребуется подключить к нашей странице, в разделе HEAD довольно много файлов (за исключением самой библиотеки эти файлы не очень большие):
<script type="text/javascript" src="js/jquery-1.2.1.js"></script> <script type="text/javascript" src="js/jquery.dimensions.js"></script> <script type="text/javascript" src="js/ui.mouse.js"></script> <script type="text/javascript" src="js/ui.draggable.js"></script> <script type="text/javascript" src="js/ui.draggable.ext.js"></script> <script type="text/javascript" src="js/ui.droppable.js"></script> <script type="text/javascript" src="js/ui.droppable.ext.js"></script>
Большинство их уже знакомы по предыдущим примерам, добавились только ui.droppable.js и ui.droppable.ext.js, которые и обеспечат нам те возможности, которые мы собираемся рассмотреть.
Не будем очень уж внимательно рассматривать таблицу стилей, поскольку здесь в основном это дело вкуса. Остановлюсь только на ее отдельных моментах.
.products { float:left; } #basket { background-color:#e9b96e; border:3px double #c17d11; width:150px; height:120px; margin:10px; padding:3px; position:absolute; top:5px; right:5px; }
В работе примера используются элементы с классом .products и идентификатором #basket (понятно, что products – это товары интернет-магазина, а basket – корзина). Никаких подводных камней тут нет, можно использовать любой стиль отображения этих элементов. Единственное, что необходимо учитывать – наш скрипт будет обращаться к этим элементам по имени класса и идентификатора.
Можно упомянуть еще два класса из таблицы стилей:
.droppable-active { outline:1px dotted #F00; } .droppable-hover { outline:1px dotted #00F; }
Класс .droppable-active будет использован скриптом в тот момент, когда процесс перемещения элемента уже начался, но перемещаемый элемент еще не находится «в зоне действия» целевого элемента. А класс .droppable-hover будет применен, когда перемещаемый элемент окажется над целевым.
Сам HTML-код вообще не представляет собой ничего особенного: несколько картинок, целевой блок, блок вывода результатов. Все это Вы сможете посмотреть, если скачаете файл примера. А вот сам JavaScript, который все это обрабатывает, разберем подробнее. Код получился немножко длинноват, но очень хотелось сделать более-менее красивый пример, а не полуфабрикат…
<script type="text/javascript"> $(document).ready(function(){ // ---- DRAGGABLES & DROPPABLES ----- $("div.products").draggable({ helper: clone, opacity: 0.5 }); $("#basket").droppable({ accept: ".products", activeClass: "droppable-active", hoverClass: "droppable-hover", drop: function(ev, ui) { var code = $(ui.draggable.element) .find("img").attr("id"); if($(this).find("div[@id="+ code +"]") .html()==null) { var name = $(ui.draggable.element) .find("img").attr("alt"); $(this).append(" <div class="basket" id=" + code + "> <input type="text" class="qnt"/> " + name + "<img src="droppable-delete.gif" class="delete" alt="Удалить" /></div> "); } // ******************* $(".delete").click(function () { $(this).parent().remove(); }); // ******************* // ******************* $("#buy").click(function () { var databox = new Array(); $("#basket").find("input[@type=text]") .each(function(){ var qnt = $(this).attr("value"); if(qnt===undefined) { qnt = 0; } var text = $(this).parent().text(); databox[databox.length] = text + " - " + qnt; }); data = databox.join(" кг, "); $("#buyResult").html("Вы заказали:" + data + " кгСпасибо за покупку!"); }); // **************** } }); // ------ DRAGGABLES & DROPPABLES ------ }); </script>
Как обычно используем $(document).ready(function(){…}); которая отслеживает момент готовности объектной модели документа (DOM). В нее «завернуто» все, что мы написали. И начнем разбираться дальше.
$("div.products").draggable({ helper: clone, opacity: 0.5 });
Это уже должно быть немножко знакомо: выбираем набор элементов DIV, имеющих класс .products и делаем любой из них свободно перемещаемым, задавая при этом некоторые опции. helper: clone – при перемещении элемента он останется на месте, а перемещать с помошью мыши мы будем его клон, opacity: 0.5 – прозрачность которого во время перемещения будет 0,5.
Дальше буду приводить код небольшими кусочками, чтобы было легче разбираться.
$("#basket").droppable({ accept: ".products", activeClass: "droppable-active", hoverClass: "droppable-hover"
Выбираем элемент с идентификатором basket и делаем его droppable – туда будем «сбрасывать» перемещаемые элементы. Далее устанавливаем необходимые опции:
accept: «.products» – «сбросить» мы можем только элементы, имеющие класс products.
activeClass: «droppable-active» – имя класса, который будет применен к #basket во время перемещения любого из элементов с классом .products, но до того, как перемещаемый элемент окажется «в зоне действия» элемента #basket.
hoverClass: «droppable-hover» – все тоже самое, только класс будет применен тогда, когда перемещаемый элемент попадет в «зону действия» элемента #basket.
В опции drop – устанавливается функция, которая должна будет выполниться в момент, когда мы «сбросили» перемещаемый элемент. Простор для фантазии – обрабатывайте данные как угодно. Я кратко немного прокомментирую, что написано дальше.
var code = $(ui.draggable.element) .find("img").attr("id");
Мы обращаемся к перемещаемому элементу, находим в нем (именно в нем) элемент img и получаем значение его атрибута id. Сохраняем в переменной code.
if($(this).find("div[@id="+ code +"]").html()==null)
Здесь будем проверять, нет ли уже в нашей корзине товара с таким же id. Для этого обратимся к элементу, который представляет собой нашу корзину (this в данном случае тоже самое, что и #basket), найдем элемент div с id равным id перемещаемого элемента (хранится в переменной code) и получим его HTML-код. Сравним с null. Если условие верное, значит такого продукта в корзине еще нет и мы можем выполнять следующие операторы, чтобы добавить товар в корзину.
var name = $(ui.draggable.element) .find("img").attr("alt");
Обращаемся к перемещаемому элементу (это уже делали, правда?), ищем img, получаем значение атрибута alt, где у нас хранится название товара.
Теперь осталось только сформировать нужный HTML-код и добавить его в корзину, т.е. в элемент #basket.
$(this).append('<p class="basket" id=' + code + '> <input class="qnt" type="text" /> ' + name + '<img src="droppable-delete.gif" class="delete" alt="Удалить" />');</p>
Тут вроде бы все достаточно понятно. И осталось написать еще пару вспомогательных функций, чтобы пример был хоть немного действующим. Приводить их еще раз тут не буду (можете посмотреть их в полном коде), просто поясню, что первая обрабатывает клик мышкой на картинке удаления товара из корзины и собственно удаляет выбранный элемент div. А вторая обходит все имеющиеся текстовые поля ввода, собирает их значения в массив, объединяет массив в строку и выводит результат в виде HTML-кода в элемент #buyResult.