—»     —»   Применяем HTML5-интерфейс перетаскивания для создания корзины товаров
  Раздел: eCommerce   Комментариев: 1  

Применяем HTML5-интерфейс перетаскивания для создания корзины товаров



Релиз HTML5 представил нам нативный функционал перетаскивания (Drag-n-Drop) для современных веб-браузеров. Это означает, что теперь у нас есть возможность перемещать элементы по экрану без необходимости использовать фреймворки вроде jQuery. На этой неделе мы как раз собрались воспользоваться преимуществом этого функционала для создания базовой корзины товаров для интернет-магазина. Базовый функционал, о котором мы собираемся рассказать, включает в себя возможность добавлять единицы в корзину (к тому же, если такая же единица уже находится в корзине, то интерфейс просто обновит количество приобретаемых товаров).

Применяем HTML5-интерфейс перетаскивания для создания корзины товаров

Приступаем

Для начала нам понадобится структура нашей корзины, а также список продукции. В списке продукции к каждой позиции мы добавим кастомный data-* атрибут для указания цены. Data-* атрибуты позволяют нам хранить данные с названиями для определенных элементов. Позже в этом руководстве мы будем и дальше их использовать.

<section id="cart" class="shopping-cart">
<ul>
</ul>
<span class="total">0.00</span>
</section>
<section id="products" class="products">
<ul>
<li id="product-1" data-price="2.00"><span>Product 1</span></li>
<li id="product-2" data-price="3.00"><span>Product 2</span></li>
<li id="product-3" data-price="2.99"><span>Product 3</span></li>
<li id="product-4" data-price="3.50"><span>Product 4</span></li>
<li id="product-5" data-price="4.25"><span>Product 5</span></li>
<li id="product-6" data-price="6.75"><span>Product 6</span></li>
<li id="product-7" data-price="1.99"><span>Product 7</span></li>
</ul>
</section>

Делаем процесс более простым

Так как это руководство посвящено сугубо javascript, у нас не будет доступа к ярлыкам событий jQuery (или других фреймворков). Чтобы облегчить процесс, мы воспользуемся функцией addEvent, которая позволит нам гораздо проще и быстрее добавлять события.

function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined' && element.attachEvent)
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}

Первое событие, которое мы будем использовать, это readystatechange. Это событие запускается при изменении состояния документа. Мы подождем, пока состояние будет выставлено на complete перед тем, как привязывать остальные события и логику. Это отличная альтернатива jQuery-событию .ready.

addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;
});

Опрашиваем DOM

Вместе с выходом HTML5, были обновлены и API DOM-селекторов. Также был добавлен один из наиболее применимых методов – querySelectorAll. Этот метод позволяет нам использовать более сложные стилевые css-селекторы (как jQuery) для опроса элементов. Им гораздо проще пользоваться, нежели старым методом с использованием классов и get-функциями ID.

var items = document.querySelectorAll("section.products ul li");
var cart = document.querySelectorAll("#cart ul")[0];

Здесь мы кэшируем список позиций и список корзины для дальнейшего применения. Как видно, функция querySelectorAll в значительной степени все облегчила. Теперь, когда у нас есть список позиций, нам нужно реализовать в нем возможность перетаскивать объекты, и добавить событие для установки данных при перетаскивании позиций. Чтобы сделать это, мы пройдемся по списку позиций и используем метод setAttribute, чтобы выставить атрибут draggable на true. На данном этапе нам также нужно добавить событие dragstart к каждой позиции.

for (var i = 0; i < items.length; i++) {
var item = items[i];
item.setAttribute("draggable", "true");
addEvent(item, 'dragstart', onDrag);
};

Здесь вы можете видеть, что мы указали функцию для dragstart на onDrag. Предназначение данное функции заключается в установке опций перетаскивания и хранении id элемента для дальнейшего использования при помощи dataTransfer.setData. Объект event.dataTransfer позволяет нам указать стандартные эффекты для перетаскивания. По умолчанию здесь используются как копирование, так и перемещение, но в нашем случае мы принудительно устанавливаем только перемещение.

function onDrag(event){
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.dropEffect = "move";
var target = event.target || event.srcElement;
var success = event.dataTransfer.setData('Text', target.id);
}

Применяем HTML5-интерфейс перетаскивания для создания корзины товаров

Настраиваем область перетаскивания корзины

По умолчанию элементы не позволяют применять события drop, так что, чтобы подключить эту функцию к элементу, нам нужно переписать его стандартное поведение. Чтобы сделать это, мы воспользуемся функцией под названием onDragOver. Все что она делает, это приостанавливает стандартное поведение dragover и dragenter

function onDragOver(event){
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
return false;
}
addEvent(cart, 'dragover', onDragOver);

Добавляем единицы в корзину

Теперь, когда список в корзине допускает события drop, мы можем создать нашу функцию onDrop. Опять же, первое, что нам нужно сделать, это приостановить стандартное поведение события, и как только это будет сделано, мы просто извлекаем значением id из объекта dataTransfer, но на этот раз при помощи функции dataTransfer.getData. Используя id, теперь мы можем найти единицу в списке товаров.

Перед тем, как мы добавим новый товар в корзину, сначала нам нужно проверить, не был ли он ранее уже добавлен туда. Ранее мы отмечали, что мы можем использовать больше data-* атрибутов – id продукта будет следующим из них. Чтобы проверить, нет ли продукта в корзине, мы снова используем функцию querySelectorAll, которая на этот раз определяет атрибут на основе селектора, предлагая id продукта в качестве значения.

var exists = document.querySelectorAll("#cart ul li[data-id='" + id + "']");

Теперь мы можем видеть, находится ли данный продукт в корзине, при помощи свойства .length.

if(exists.length > 0){
updateCartItem(exists[0]);
} else {
addCartItem(item, id);
}

Если корзина не содержит такого продукта, прежде всего функция addCartItem должна клонировать текущий список продуктов. Теперь мы можем начать устанавливать значения data-*. Первое, что мы добавляем, это атрибут data-d, - он будет id элемента выше. Далее мы устанавливаем количество на 1 и убираем атрибут id (так как он должен быть уникальным на странице). Нам также нужно добавить в список товаров 2 новых span-элемента. Это будут display-элементы для количества и общего количества продукта.

function addCartItem(item, id) {
var clone = item.cloneNode(true);
clone.setAttribute('data-id', id);
clone.setAttribute('data-quantity', 1);
clone.removeAttribute('id');

var fragment = document.createElement('span');
fragment.setAttribute('class', 'quantity');
fragment.innerHTML = ' x 1';
clone.appendChild(fragment);

fragment = document.createElement('span');
fragment.setAttribute('class', 'sub-total');
clone.appendChild(fragment);
cart.appendChild(clone);
}

Применяем HTML5-интерфейс перетаскивания для создания корзины товаров

Обновляем список товаров в корзине

Если позиция уже есть в корзине, нам нужно будет увеличить количество на 1, и затем обновить отображение значения отображения (display). Используя функцию getAttribute мы можем восстановить наше текущее количество, и затем увеличить его и обновить span-элемент количества.

function updateCartItem(item){
var quantity = item.getAttribute('data-quantity');
quantity = parseInt(quantity) + 1
item.setAttribute('data-quantity', quantity);
var span = item.querySelectorAll('span.quantity');
span[0].innerHTML = ' x ' + quantity;
}

Обновляем итоговый показатель

Как только количество товаров было обновлено, нам нужно по новой рассчитать общее количество. Опять же, используя функцию querySelectorAll, мы выбираем список товаров в коризне, а затем у каждого из товаров подсчитываем общее количество. Здесь мы используем функцию parseFloat, которая позволяет нам быть уверенными в том, что мы ничего не упускаем. Перед тем, как обновить значение display, мы используем функцию toFixed для ограничения количества места для десятичных чисел до 2.

function updateCart(){
var total = 0.0;
var cart_items = document.querySelectorAll("#cart ul li")
for (var i = 0; i < cart_items.length; i++) {
var cart_item = cart_items[i];
var quantity = cart_item.getAttribute('data-quantity');
var price = cart_item.getAttribute('data-price');

var sub_total = parseFloat(quantity * parseFloat(price));
cart_item.querySelectorAll("span.sub-total")[0].innerHTML = " = " + sub_total.toFixed(2);

total += sub_total;
}

document.querySelectorAll("#cart span.total")[0].innerHTML = total.toFixed(2);
}

Применяем HTML5-интерфейс перетаскивания для создания корзины товаров

Подытожим

Итак, все готово! Теперь у вас есть простая динамическая корзина товаров. Мы специально здесь опустили функцию удаления товаров из корзины, чтобы вы сами попробовали ее реализовать. Это не очень сложно, и существует множество способов, посредством которых вы можете ее реализовать. Только помните, что в самом конце нужно запускать функцию updateCart.

Финальный javascript-код должен выглядеть следующим образом:

function addEvent(element, event, delegate ) {
if (typeof (window.event) != 'undefined')
element.attachEvent('on' + event, delegate);
else
element.addEventListener(event, delegate, false);
}

addEvent(document, 'readystatechange', function() {
if ( document.readyState !== "complete" )
return true;

var items = document.querySelectorAll("section.products ul li");
var cart = document.querySelectorAll("#cart ul")[0];

function updateCart(){
var total = 0.0;
var cart_items = document.querySelectorAll("#cart ul li")
for (var i = 0; i < cart_items.length; i++) {
var cart_item = cart_items[i];
var quantity = cart_item.getAttribute('data-quantity');
var price = cart_item.getAttribute('data-price');

var sub_total = parseFloat(quantity * parseFloat(price));
cart_item.querySelectorAll("span.sub-total")[0].innerHTML = " = " + sub_total.toFixed(2);

total += sub_total;
}

document.querySelectorAll("#cart span.total")[0].innerHTML = total.toFixed(2);
}

function addCartItem(item, id) {
var clone = item.cloneNode(true);
clone.setAttribute('data-id', id);
clone.setAttribute('data-quantity', 1);
clone.removeAttribute('id');

var fragment = document.createElement('span');
fragment.setAttribute('class', 'quantity');
fragment.innerHTML = ' x 1';
clone.appendChild(fragment);

fragment = document.createElement('span');
fragment.setAttribute('class', 'sub-total');
clone.appendChild(fragment);
cart.appendChild(clone);
}

function updateCartItem(item){
var quantity = item.getAttribute('data-quantity');
quantity = parseInt(quantity) + 1
item.setAttribute('data-quantity', quantity);
var span = item.querySelectorAll('span.quantity');
span[0].innerHTML = ' x ' + quantity;
}

function onDrop(event){
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;

var id = event.dataTransfer.getData("Text");
var item = document.getElementById(id);

var exists = document.querySelectorAll("#cart ul li[data-id='" + id + "']");

if(exists.length > 0){
updateCartItem(exists[0]);
} else {
addCartItem(item, id);
}

updateCart();

return false;
}

function onDragOver(event){
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
return false;
}

addEvent(cart, 'drop', onDrop);
addEvent(cart, 'dragover', onDragOver);

function onDrag(event){
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.dropEffect = "move";
var target = event.target || event.srcElement;
var success = event.dataTransfer.setData('Text', target.id);
}


for (var i = 0; i < items.length; i++) {
var item = items[i];
item.setAttribute("draggable", "true");
addEvent(item, 'dragstart', onDrag);
};
});

Здесь вы можете ознакомиться с демо, в котором используется простой код CSS только для того, чтобы подсветить 2 раздела.

Посмотреть демо | Скачать исходные файлы
Обнаружили ошибку или мёртвую ссылку?
Выделите проблемный фрагмент мышкой и нажмите CTRL+ENTER.
В появившемся окне опишите проблему и отправьте уведомление Администрации ресурса.
Нужна органическая вечная ссылка из данной статьи? Постовой?
Подробности здесь
Вам понравился материал? Поблагодарить легко!
Будем весьма признательны, если поделитесь этой статьей в социальных сетях:

Опубликовал Design FactoRy   Прочитано (раз): 5892   |   Оставлено комментариев: 1
Автор перевода — CoolWebmasters.Com ©   |   Источник материала / оригинал статьи   Распечатать
Другие статьи и новости по теме:
Комментарий #1: 15 октября 2013 @ 00:27
Написал: krapan88 — группа: Читатели  
На сайте с: 31.01.2010   |   Публикаций: 0   |   Комментариев: 59
ICQ: --- не указано ---
А где тут HTML5? Тэг section + атрибут data-* ?
Добавление комментария
Уважаемые пользователи!
При добавлении комментариев на сайт Вам следует учитывать следующее - все комментарии проверяются Администрацией на предмет отсутствия спама. При обнаружении признаков спама, в оставленном Вами комментарии, сам комментарий будет незамедлительно удалён, а Ваш IP-адрес будет забанен без предупреждения! Учётные записи пользователей, рассылающих спам, блокируются/удаляются без права последующего восстановления.

С уважением, Администрация сайта.
* = поля обязательны к заполнению
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Вопрос : Назовите месяц February по-русски
Подтверждение кода безопасности :

Включите эту картинку для отображения кода безопасности
обновить, если не виден код


Популярные публикации


















Свежие шаблоны сайтов каждый день
С миру по нитке
«    Июнь 2017    »
ПнВтСрЧтПтСбВс
 1234
567891011
12131415161718
19202122232425
2627282930