Корзина покупателя на jQuery.

Плагин jqCart.

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

  1. Хоть код и оформлен в виде плагина, но плагином его можно назвать с большой натяжкой. Да и вообще, в этом направлении, на мой взгляд, сделать плагин полностью универсальным - достаточно сложно;
  2. Писа́лся плагин на скорую руку, поэтому достаточно сыроват, хотя и вполне рабочий;
  3. На данный момент, код не документированный;
  4. Планирую ли я его дорабатывать? Да, но при достаточном количестве свободного времени;

Итак, для работы плагина требуется библиотека jQuery >= 1.8, которая должна быть подключена до подключения самого плагина. Работать должно во всех современных браузера и, по идее, даже в IE8. Проблема для старых "осликов", может заключаться только в применяемых CSS-свойствах и версии jQuery (напомню, что jQuery 2.x - не поддерживает Internet Explorer 6, 7, и 8). Данные передаются на сервер с помощью Ajax и поэтому, я крайне рекомендую использовать кодировку для файлов UTF-8 без BOM!

Подключение:

<link href="css/jqcart.css" rel="stylesheet" type="text/css">
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/jqcart.min.js"></script>

Использование:

$(function() {
    'use strict';
    // инициализация плагина
    $.jqCart({
        buttons: '.add_item',        // селектор кнопок, аля "Добавить в корзину"
        handler: '/php/handler.php', // путь к обработчику
        visibleLabel: false,         // показывать/скрывать ярлык при пустой корзине (по умолчанию: false)
        openByAdding: false,         // автоматически открывать корзину при добавлении товара (по умолчанию: false)
        currency: '&euro;',          // валюта: строковое значение, мнемоники (по умолчанию "$")
        cartLabel: '.label-place'    /* селектор элемента, где будет размещен ярлык, 
                                        он же - "кнопка" для открытия корзины */
    });
    
    // дополнительные методы
    $.jqCart('openCart'); // открыть корзину
    $.jqCart('clearCart'); // очистить корзину
});

В кнопках ("Добавить в корзину"), должены быть прописаны следующие data-атрибуты:

  1. data-id - ID товара
  2. data-title - Наименование товара
  3. data-price - Цена товара
  4. data-img - URL фото товара (опционально)

Все значения вышеуказанных data-атрибутов, принимают участие при формировании окна корзины. Можно добавлять дополнительные data-атрибуты, значения которых будут отправлены с остальными данными в обработчик. Ключи в полученном массиве на сервере, будут соответствовать имени атрибута после "data-", т.е. значение атрибута "data-somevalue", будет в массиве под ключем "somevalue" Тег для кнопки и её расположение на странице - значения не имеет.

Пример:

<button class="add_item" data-id="7" data-title="Bugatti Veyron Super Sports" data-price="200" data-img="http://site.com/img/photo.png">Добавить в корзину</button>

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

<?php
// какой-то код обработки заказа...

// Ответ на запрос
// !для версии PHP < 5.4, используйте традиционный синтаксис инициализации массивов array() вместо короткого []
$response = [
    'errors' => !$send_ok,
    'message' => $send_ok ? 'Заказ принят в обработку!' : 'Хьюстон! У нас проблемы!'
];
exit( json_encode($response) );

Где переменная $send_ok - булевое значение (true/false), в зависимости от результата обработки заказа. Если это будет отправка на почту, то можно так:

<?php
$send_ok = mail($to, $subject, $body, implode("\r\n", $headers));

Ахтунг! В обработчике я не делал фильтрацию данных, поэтому внимательно и тщательно их обрабатывайте перед использованием, а особенно, если вы собираетесь записывать данные в БД!

Версия 1.1.0

  • Данные распределены по разным data-атрибутам кнопки
  • Добавлена возможность отображения фото товара в корзине
  • Добавлен параметр currency для вывода в корзине валюты рядом со стоимостью и ценой
  • Добавлена возможность передавать на сервер дополнительные данные, которые берутся из пользовательских data-атрибутов кнопки

Версия 1.1.1

  • Добавлена опция visibleLabel. Показывать ярлык при пустой корзине
  • Добавлена опция openByAdding. Автоматически открывать корзину при добавлении товара
  • Добавлена кнопка вывода заказа на печать

Версия 1.1.2

  • Исправлен расчет сумм с плавающей точкой

Просьба описывать в комментариях найденные вами ошибки/баги. По мере возможностей, я буду их править, НО глобальными изменениями или дополнениями, буду заниматься, как уже говорил, при наличии свободного времени

Incode Pro logo

807 комментариев

Страница 15 из 33  
Гость 15.01.2018 00:46
Подскажите как реализовать вместо alert "заказ принят в обработку" сделать переход на новую страницу?
Гость 15.01.2018 23:18
Например для оплаты...
Incode 16.01.2018 00:23
вместо alert "заказ принят в обработку" сделать переход на новую страницу?
Неминимизированный файл (jqcart.js) > метод sendOrder > метод $.ajax() > callback-функция success. Допишите нужный вам функционал. Например, для переадресации на другую страницу:
location.href = 'path/to/another/page.html';

Не забудьте, что в примере подключается сжатый файл плагина (jqcart.min.js), поэтому после изменений замените на отредактированный.
Гость 16.01.2018 15:33
SOS!!!!
Помогите кодом!!! Как отправить данные из корзины в базу?
Incode 16.01.2018 18:16
Как отправить данные из корзины в базу?
С чем именно возникли сложности?
Гость 18.01.2018 00:19
Incode 16.01.2018 18:16
Как отправить данные из корзины в базу?
С чем именно возникли сложности?


Я не работала с массивами. Нужно в базу записать каждый элемент массива.
Incode 18.01.2018 01:45
Я не работала с массивами. Нужно в базу
До этого момента, я был уверен, что для этого в первую очередь требуется умение работать с БД, а не с массивами, тем более, что в примере обработчика можно посмотреть, в какой переменной какие данные содержаться (они подставляются в тело письма).
Ладно... Для того, чтобы помочь вам составить запрос в базу, нужно, как минимум, знать имена полей и имя таблицы, куда эти данные будут записываться.
Гость 18.01.2018 08:18
До этого момента, я был уверен, что для этого в первую очередь требуется умение работать с БД, а не с массивами, тем более, что в примере обработчика можно посмотреть, в какой переменной какие данные содержаться (они подставляются в тело письма).
Ладно... Для того, чтобы помочь вам составить запрос в базу, нужно, как минимум, знать имена полей и имя таблицы, куда эти данные будут записываться.

Спасибо, что можете помочь) Можно просто любой пример с теми данными что уже передаются в корзину. По аналогии можно будет уже и со своими данными проработать. Мне главное сам принцип передачи.
Incode 18.01.2018 11:44
Можно просто любой пример
Можно
<?php
// Подключаемся к базе (данные доступа изменить на свои)
$dbh = new \PDO('mysql:host=localhost;dbname=MY_DATABASE', 'MY_USERNAME', 'MY_PASSWORD'); 
// Записываем в таблицу order основные данные по заказу
$query = "INSERT INTO `order` (`username`, `email`, `telephone`, `address`, `comment`) VALUES (?, ?, ?, ?, ?)";
$sth = $dbh->prepare($query);
$sth->execute([
    $userdata['user_name'],
    $userdata['user_mail'],
    $userdata['user_phone'],
    $userdata['user_address'],
    $userdata['user_comment'],
]);
// Если заказ успешно записан, то получаем ID заказа (!должно быть поле с автоинкрементом)
if($order_id = $dbh->lastInsertId()) {
    // Записываем в таблицу order_product каждый из заказанных товаров, с привязкой к ID заказа
    $query = "INSERT INTO `order_product` (`order_id`, `product_name`, `price`, `count`) VALUES (?, ?, ?, ?)";
    $sth = $dbh->prepare($query);
    foreach($orderlist as $id => $item_data) {
        $sth->execute([
            $order_id,
            $item_data['title'],
            $item_data['price'],
            $item_data['count']
        ]);
    }
    // * Другим вариантом, может быть сгененрирована строка запроса с "мультивставкой"
    // и запрос выполняется один раз, а не в цикле.
    // Пример такого запроса:
    // INSERT INTO tbl_name (a,b,c) VALUES (1,2,3),(4,5,6),(7,8,9);
}
Гость 18.01.2018 14:12
Можно

Огромное спасибо. Пойду попробую применить)
Гость 19.01.2018 13:56
Добавил кнопку в корзину, почему-то не работает. Может кто подскажет где ошибка?

$(document)
.on('click', opts.buttons, actions.addToCart)
.on('click', '.jqcart-layout', function (e) {
if (e.target === this) {
actions.hideCart();
}
})
.on('click', '.jqcart-incr', actions.changeAmount)
.on('input keyup', '.jqcart-amount', actions.changeAmount)
.on('click', '.jqcart-del-item', actions.delFromCart)
.on('submit', '.jqcart-orderform', actions.sendOrder)
.on('submit', '.jqcart-orderform', actions.sendpayOrder)- добавил кнопку
.on('reset', '.jqcart-orderform', actions.hideCart)
.on('click', '.jqcart-print-order', actions.printOrder);
return false;
},


sendOrder: function (e) {
e.preventDefault();
var $that = $(this);
// Проверка на пустые поля для имени и телефона юзера
if ($.trim($('[name=user_name]', $that).val()) === '' || $.trim($('[name=user_phone]', $that).val()) === '') {
$('<p class="jqcart-error">Пожалуйста, укажите свое имя и контактный телефон!</p>').insertBefore($that).delay(3000).fadeOut();
return false;
}
// Ajax запрос на сервер
$.ajax({
url: opts.handler,
type: 'POST',
dataType: 'json',
data: {
orderlist: $.param(actions.getStorage()),
userdata: $that.serialize()
},
error: function () {
},
success: function (resp) {
$('.jqcart-checkout').html('<p>' + resp.message + '</p>');
if (!resp.errors) {
setTimeout(methods.clearCart, 2000);
}
}
});
},
sendpayOrder: function (e) {
e.preventDefault();
var $that = $(this);
// Проверка на пустые поля для имени и телефона юзера
if ($.trim($('[name=user_name]', $that).val()) === '' || $.trim($('[name=user_phone]', $that).val()) === '') {
$('<p class="jqcart-error">Пожалуйста, укажите свое имя и контактный телефон!</p>').insertBefore($that).delay(3000).fadeOut();
return false;
}
// Ajax запрос на сервер
$.ajax({
url: opts.handler,
type: 'POST',
dataType: 'json',
data: {
orderlist: $.param(actions.getStorage()),
userdata: $that.serialize()
},
error: function () {
},
success: function (resp) {
$('.jqcart-checkout').html('<p>' + resp.message + '</p>');
if (!resp.errors) {
setTimeout(methods.clearCart, 2000);
location.href = "/templates/pay.php"; //- переход на страницу оплаты
}
}
});
},
Гость 20.01.2018 00:13
Добавил кнопку в корзину, почему-то не работает. Может кто подскажет где ошибка?


А в jqcart.min.js добавили?
Гость 20.01.2018 01:06
А в jqcart.min.js добавили?


success:function(b){d(".jqcart-checkout").html("<p>"+b.message+"</p>");b.errors||setTimeout(m.clearCart,2E3);location.href = "/templates/pay.php";}})} 
Гость 21.01.2018 21:31
А в jqcart.min.js добавили?

добавил в jqcart.js Почему-то и с кнопки отправить заказ и с кнопки оплатить заказ - переходит на страницу оплаты...
Incode 21.01.2018 23:00
Почему-то
Потому, что вы установили на форму два обработчика события submit. Достаточно заменить функционал в одном методе, или из него вызывать еще свой дописанный метод для каких-то определенных задач.
spoon 23.01.2018 06:14
Не могу передать переменные в php.
Вот строка в jq
g += '<div class="jqcart-delivery">Доставка: <span class="text">Самовывоз</span> Цена: <span class="sum">0</span> ' + h.currency + ' </div>';

Так делаю в php
<td style="border: 1px solid #333333; padding: 5px;" colspan="3">Доставка: '.$userdata['text'].'</td>
<td style="border: 1px solid #333333; padding: 5px;" colspan="1"><b>Стоимость:
'.$userdata['sum'].'</b></td>

На почту не передаются '.$userdata['text'].' и '.$userdata['sum'].' подскажите, что не так.
Incode 23.01.2018 12:34
@spoon, Данные передаются из элементов форм: input, textarea и т.д. В вашем HTML-коде, я не наблюдаю полей с атрибутом name="text" и name="sum". Или вы их не показали, или же их не существует. Если второе, то добавьте, например, скрытые поля с нужными именами и значениями:
g += '<input type="hidden" name="text" value="Самовывоз">';
g += '<input type="hidden" name="sum" value="0">';
Эти элементы должны быть обязательно внутри форы!
Гость 23.01.2018 12:57

Incode 21.01.2018 23:00

Почему-то

Потому, что вы установили на форму два обработчика события submit. Достаточно заменить функционал в одном методе, или из него вызывать еще свой дописанный метод для каких-то определенных задач.


А если submit2 поставить, тоже не работает?
Incode 23.01.2018 12:59
А если submit2 поставить, тоже не работает?
submit - это событие отправки данных формы. А события submit2 - не существует.
spoon 24.01.2018 13:53
Данные передаются из элементов форм: input, textarea и т.д. В вашем HTML-коде, я не наблюдаю полей с атрибутом name="text" и name="sum".


Что то я не догоняю)) У меня в это поле
g += '<div class="jqcart-delivery">Доставка: <span class="text">Самовывоз</span> Цена: <span class="sum">0</span> ' + h.currency + ' </div>';


По этому скрипту
$(document).on('change', '#myselect', function() {
	var $that = $(this),
	delivery = $('.jqcart-delivery');
	delivery.find('.text').text($(':selected', $that).text());
	delivery.find('.sum').text($that.val());
});


из селектора попадают значения Доставка и Стоимость доставки.

Если я сделаю скрытые инпуты
g += '<input type="hidden" name="text" value="Самовывоз">';
g += '<input type="hidden" name="sum" value="0">';

то как в них будут попадать значения из селектора?
Incode 24.01.2018 14:30
как в них будут попадать значения
Подставлять значения в атрибуты value так же, как подставляете значения в элементы с классом "text" и "sum". Только если в первом случае вы ипользовали метод .text(), то для полей формы используют метод .val()
spoon 25.01.2018 16:04
Всё сделал, всё работает, спасибо.
Теперь прикручиваю Итоговую стоимость со стоимостью доставки, пришлось Итого сделать глобальной, т.к. передать значение переменной b не мог она была внутри метода openCart: function().
Вроде все работает но Итоговая стоимость передается в другую функцию и при изменении её она не меняется в итоговой стоимости с доставкой.
Вот расчет доставки

$(document).on('change', '#myselect', function() {
    var delivery = $('.jqcart-delivery');
    var selectedText = $(this).find(':selected').text();
    var selectedVal = $(this).find(':selected').val();
  
    delivery.find('.text').text(selectedText);
    delivery.find('.sum').text(selectedVal);
    
    var globalsum = Math.ceil(+selectedVal + +globalper);
    $('.summ').text(globalsum);
  
  $('[name="text"]').val(selectedText);
  $('[name="sum"]').val(selectedVal);
  $('[name="summ"]').val(globalsum);
});


var globalper;-глобальная переменная Итого, заменил b на globalper

var globalper;
openCart: function() {
//var b = 0;
globalper = 0;
a = c.getStorage();
g = '<p class="jqcart-cart-title">Корзина<span class="jqcart-print-order">...;
var e;
for (e in a)
if (a.hasOwnProperty(e)) {
var k = Math.ceil(a[e].count * a[e].price * 100) / 100;
globalper = Math.ceil(100 * (globalper + k)) / 100;
//
//
b = globalper ? g + '<p class="jqcart-cart-title">Контактная информация:</p><form class="


Я понимаю так, что надо замкнуть работу метода openCart: function() в функции расчета стоимости доставки?
Гость 26.01.2018 00:00
Корзина хорошая, единственно при нажатии на корзину повторно, она открывается поверх уже открытой и так много раз можно сделать.
Гость 26.01.2018 14:31
А подскажите пожалуйста, как итоговую сумму вставить в форму оплаты:

<iframe src="https://money.yandex.ru/quickpay/shop-widget?writer=seller&targets=&targets-hint=&default-sum='globalper'&button-text=11&payment-type-choice=on&mobile-payment-type-choice=on&fio=on&phone=on&mail=on&address=on&hint=&successURL=Armelle-52.ru&quickpay=shop&account=4100000000000" width="450" height="233" frameborder="0" allowtransparency="true" scrolling="no"></iframe>
Гость 26.01.2018 22:29
А как сделать в этой корзине, чтобы можно было стереть количество товара, чтобы он не подставлял единицу все время?
Страница 15 из 33  
Ваш комментарий:
X