Closed UralZima closed 6 years ago
That option is not implemented right now, but will be added. Thank you
I implemented it on my side. I am not good git user, so I can just show some pieces of code:
init function: var mi=this; var stor=localStorage.getItem('cart'); if(stor!==null) { var load = $.parseJSON(stor); $.each( load, function( i, n ) { mi._addToCart(n,false); }); }
_addToCart: function (p,store) { store = typeof store !== 'undefined' ? store : true; .... if(store) localStorage.setItem('cart', JSON.stringify(this.cart)); }
_removeFromCart: function (unique_key) { localStorage.setItem('cart', JSON.stringify(this.cart)); }
can you share full code
Hi. My code is so modified and rewritten. so my code will not help you. I can help you explain what I added and how it works. The piece of code on init function loads all items to cart from storage, and passed false to addToCart as second arg.
for addToCart function I added a second argument, so I am not rewriting storage when doing load on init. The item is added to localstorage if second arg is true or undefined (actually I always rewrite localStorage variable with current cart list from this.cart variable)
on remove from cart function it rewrites localstorage with current cart list.
Hello again,
Hello,
I can adding JSON results to php variable, and I can record in to db. But main problem is when I page refresh, cart items will be removing.
add JSON results to php variables: $product_list_array = json_decode($product_list,true); foreach ($product_list_array as $value1){ echo $id = $value1['urun_id']; echo $urun_adi = $value1['urun_adi']; echo $urun_resmi = ""; echo $urun_aciklama = $value1['urun_aciklama']; echo $urun_adeti = $value1['urun_adeti']; echo $urun_fiyati = $value1['urun_fiyati']; echo $product_size = $value1['product_size']; echo $unique_key = $value1['unique_key']; }
My solution is on client side, the cart is saving to browser's local storage and is not passed to php in any way. If you want to save cart on server side, share the full code, and I'll try to help you, from your code and description I didn't understand what is the problem.
I want save cart items to cookie or session, then I need read cart items from cookie or session when if I need it..
You can't save much information into cookie. That's why you need to use localstorage. Just modify cart code with my code (saves to localstorage) and implement a submit method, which send cart contents to php.
ok, can you share your code (saves to localstorage)?
I already did it in first post and described you in details earlier. You just need to read it carefully and add/modify a few lines.
Which lines I can not understand, can you modify it?
var defaults = {
cart: [], // initial products on cart
resultName: 'cart_list', // Submit name of the cart parameter
theme: 'default', // theme for the cart, related css need to include for other than default theme
combineProducts: true, // combine similar products on cart
highlightEffect: true, // highlight effect on adding/updating product in cart
cartItemTemplate: '<img class="img-responsive pull-left" src="{urun_resmi}" /><h4 class="list-group-item-heading">{urun_adi}</h4><p class="list-group-item-text">{urun_aciklama}</p>',
cartItemQtyTemplate: '{display_price} × {display_quantity} = {display_amount}',
productContainerSelector: '.sc-product-item',
productElementSelector: '*', // input, textarea, select, div, p
addCartSelector: '.sc-add-to-cart',
paramSettings: { // Map the paramters
productPrice: 'urun_fiyati',
productQuantity: 'urun_adeti',
productName: 'urun_adi',
productId: 'urun_id'
},
lang: { // Language variables
cartTitle: '<i class="fa fa-shopping-cart"></i> Sepetim',
checkout: 'Alışverişi Tamamla <i class="fa fa-chevron-right"></i>',
clear: 'Sepeti Boşalt',
subtotal: 'Genel Toplam:',
cartRemove: '×',
cartEmpty: 'Sepetin şu an boş<br />Ürün ekle'
},
submitSettings: {
submitType: 'form', // form, paypal, ajax
ajaxURL: '', // Ajax submit URL
ajaxSettings: {} // Ajax extra settings for submit call
},
currencySettings: {
locales: 'tr-TR', // A string with a BCP 47 language tag, or an array of such strings
currencyOptions: {
style: 'currency',
currency: 'TRY',
currencyDisplay: 'symbol'
} // extra settings for the currency formatter. Refer: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
},
toolbarSettings: {
showToolbar: true,
showCheckoutButton: true,
showClearButton: true,
showCartSummary: true,
checkoutButtonStyle: 'default', // default, paypal, image
checkoutButtonImage: '', // image for the checkout button
toolbarExtraButtons: [] // Extra buttons to show on toolbar, array of jQuery input/buttons elements
},
debug: false
};
// The plugin constructor
function SmartCart(element, options) {
// Merge user settings with default, recursively
this.options = $.extend(true, {}, defaults, options);
// Cart array
this.cart = [];
// Cart element
this.cart_element = $(element);
// Call initial method
this.init();
}
$.extend(SmartCart.prototype, {
init: function () {
// Set the elements
this._setElements();
// Add toolbar
this._setToolbar();
// Assign plugin events
this._setEvents();
// Set initial products
var mi = this;
$(this.options.cart).each(function (i, p) {
p = mi._addToCart(p);
});
// Call UI sync
this._hasCartChange();
},
// PRIVATE FUNCTIONS
/*
* Set basic elements for the cart
*/
_setElements: function () {
// The element store all cart data and submit with form
var cartListElement = $('<input type="hidden" name="' + this.options.resultName + '" id="' + this.options.resultName + '" />');
this.cart_element.append(cartListElement);
// Set the cart main element
this.cart_element.addClass('panel panel-default sc-cart sc-theme-' + this.options.theme);
this.cart_element.append('<div class="panel-heading sc-cart-heading">' + this.options.lang.cartTitle + ' <span class="sc-cart-count badge">0</span></div>');
this.cart_element.append('<div class="list-group sc-cart-item-list"></div>');
},
/*
* Set the toolbar for the cart
*/
_setToolbar: function () {
if (this.options.toolbarSettings.showToolbar !== true) {
return false;
}
var toolbar = $('<div></div>').addClass('panel-footer sc-toolbar');
var toolbarButtonPanel = $('<div class="sc-cart-toolbar">');
var toolbarSummaryPanel = $('<div class="sc-cart-summary">');
// Checkout Button
if (this.options.toolbarSettings.showCheckoutButton) {
var btnCheckout = '';
switch (this.options.toolbarSettings.checkoutButtonStyle) {
case 'paypal':
btnCheckout = '<button class="sc-button-checkout-paypal sc-cart-checkout" type="submit"><img src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/checkout-logo-medium.png" alt="Check out with PayPal" /></button>';
break;
case 'image':
btnCheckout = '<button class="sc-button-checkout-paypal sc-cart-checkout" type="submit"><img src="' + this.options.toolbarSettings.checkoutButtonImage + '" alt="Check out" /></button>';
break;
default:
btnCheckout = '<button class="btn btn-success sc-cart-checkout" type="button">' + this.options.lang.checkout + '</button> ';
break;
}
toolbarButtonPanel.append(btnCheckout);
}
// Clear Button
if (this.options.toolbarSettings.showClearButton) {
var btnClear = $('<button class="btn btn-danger sc-cart-clear" type="button">').text(this.options.lang.clear);
toolbarButtonPanel.append(btnClear);
}
// Add extra toolbar buttons
if (this.options.toolbarSettings.toolbarExtraButtons && this.options.toolbarSettings.toolbarExtraButtons.length > 0) {
toolbarButtonPanel.append(this.options.toolbarSettings.toolbarExtraButtons);
}
// Cart Summary
if (this.options.toolbarSettings.showCartSummary) {
var panelSubTotal = $('<div class="sc-cart-summary-subtotal">');
panelSubTotal.append(this.options.lang.subtotal).append(' <span class="sc-cart-subtotal">0</span>');
toolbarSummaryPanel.append(panelSubTotal);
}
toolbar.append(toolbarSummaryPanel);
toolbar.append(toolbarButtonPanel);
this.cart_element.append(toolbar);
},
/*
* Set events for the cart
*/
_setEvents: function () {
var mi = this;
// Capture add to cart button events
$(this.options.addCartSelector).on("click", function (e) {
e.preventDefault();
var p = mi._getProductDetails($(this));
p = mi._addToCart(p);
$(this).parents(mi.options.productContainerSelector).addClass('sc-added-item').attr('data-product-unique-key', p.unique_key);
});
// Item remove event
$(this.cart_element).on("click", '.sc-cart-remove', function (e) {
e.preventDefault();
$(this).parents('.sc-cart-item').fadeOut("normal", function () {
mi._removeFromCart($(this).data('unique-key'));
$(this).remove();
mi._hasCartChange();
});
});
// Item quantity change event
$(this.cart_element).on("change", '.sc-cart-item-qty', function (e) {
e.preventDefault();
mi._updateCartQuantity($(this).parents('.sc-cart-item').data('unique-key'), $(this).val());
});
// Cart checkout event
$(this.cart_element).on("click", '.sc-cart-checkout', function (e) {
if ($(this).hasClass('disabled')) {
return false;
}
e.preventDefault();
mi._submitCart();
});
// Cart clear event
$(this.cart_element).on("click", '.sc-cart-clear', function (e) {
if ($(this).hasClass('disabled')) {
return false;
}
e.preventDefault();
$('.sc-cart-item-list > .sc-cart-item', this.cart_element).fadeOut("normal", function () {
$(this).remove();
mi._clearCart();
mi._hasCartChange();
});
});
},
/*
* Get the parameters of a product by seaching elements with name attribute/data.
* Product details will be return as an object
*/
_getProductDetails: function (elm) {
var mi = this;
var p = {};
elm.parents(this.options.productContainerSelector).find(this.options.productElementSelector).each(function () {
if ($(this).is('[name]') === true || typeof $(this).data('name') !== typeof undefined) {
var key = $(this).attr('name') ? $(this).attr('name') : $(this).data('name');
var val = mi._getContent($(this));
if (key && val) {
p[key] = val;
}
}
});
return p;
},
/*
* Add the product object to the cart
*/
_addToCart: function (p) {
var mi = this;
if (!p.hasOwnProperty(this.options.paramSettings.productPrice)) {
this._logError('Price is not set for the item');
return false;
}
if (!p.hasOwnProperty(this.options.paramSettings.productQuantity)) {
this._logMessage('Quantity not found, default to 1');
p[this.options.paramSettings.productQuantity] = 1;
}
if (!p.hasOwnProperty('unique_key')) {
p.unique_key = this._getUniqueKey();
}
if (this.options.combineProducts) {
var pf = $.grep(this.cart, function (n, i) {
return mi._isObjectsEqual(n, p);
});
if (pf.length > 0) {
var idx = this.cart.indexOf(pf[0]);
this.cart[idx][this.options.paramSettings.productQuantity] = this.cart[idx][this.options.paramSettings.productQuantity] - 0 + (p[this.options.paramSettings.productQuantity] - 0);
p = this.cart[idx];
// Trigger "itemUpdated" event
this._triggerEvent("itemUpdated", [p]);
} else {
this.cart.push(p);
// Trigger "itemAdded" event
this._triggerEvent("itemAdded", [p]);
}
} else {
this.cart.push(p);
// Trigger "itemAdded" event
this._triggerEvent("itemAdded", [p]);
}
this._addUpdateCartItem(p);
return p;
},
/*
* Remove the product object from the cart
*/
_removeFromCart: function (unique_key) {
var mi = this;
$.each(this.cart, function (i, n) {
if (n.unique_key === unique_key) {
var itemRemove = mi.cart[i];
mi.cart.splice(i, 1);
$('*[data-product-unique-key="' + unique_key + '"]').removeClass('sc-added-item');
mi._hasCartChange();
// Trigger "itemRemoved" event
this._triggerEvent("itemRemoved", [itemRemove]);
return false;
}
});
},
/*
* Clear all products from the cart
*/
_clearCart: function () {
this.cart = [];
// Trigger "cartCleared" event
this._triggerEvent("cartCleared");
this._hasCartChange();
},
/*
* Update the quantity of an item in the cart
*/
_updateCartQuantity: function (unique_key, qty) {
var mi = this;
var qv = this._getValidateNumber(qty);
$.each(this.cart, function (i, n) {
if (n.unique_key === unique_key) {
if (qv) {
mi.cart[i][mi.options.paramSettings.productQuantity] = qty;
}
mi._addUpdateCartItem(mi.cart[i]);
// Trigger "quantityUpdate" event
this._triggerEvent("quantityUpdated", [mi.cart[i], qty]);
return false;
}
});
},
/*
* Update the UI of the cart list
*/
_addUpdateCartItem: function (p) {
var productAmount = (p[this.options.paramSettings.productQuantity] - 0) * (p[this.options.paramSettings.productPrice] - 0);
var cartList = $('.sc-cart-item-list', this.cart_element);
var elmMain = cartList.find("[data-unique-key='" + p.unique_key + "']");
if (elmMain && elmMain.length > 0) {
elmMain.find(".sc-cart-item-qty").val(p[this.options.paramSettings.productQuantity]);
elmMain.find(".sc-cart-item-amount").text(this._getMoneyFormatted(productAmount));
} else {
elmMain = $('<div></div>').addClass('sc-cart-item list-group-item');
elmMain.append('<button type="button" class="sc-cart-remove">' + this.options.lang.cartRemove + '</button>');
elmMain.attr('data-unique-key', p.unique_key);
elmMain.append(this._formatTemplate(this.options.cartItemTemplate, p));
var itemSummary = '<div class="sc-cart-item-summary"><span class="sc-cart-item-price">' + this._getMoneyFormatted(p[this.options.paramSettings.productPrice]) + '</span>';
itemSummary += ' × <input type="number" min="1" max="1000" class="sc-cart-item-qty" value="' + this._getValueOrEmpty(p[this.options.paramSettings.productQuantity]) + '" />';
itemSummary += ' = <span class="sc-cart-item-amount">' + this._getMoneyFormatted(productAmount) + '</span></div>';
elmMain.append(itemSummary);
cartList.append(elmMain);
}
// Apply the highlight effect
if (this.options.highlightEffect === true) {
elmMain.addClass('sc-highlight');
setTimeout(function () {
elmMain.removeClass('sc-highlight');
}, 500);
}
this._hasCartChange();
},
/*
* Handles the changes in the cart
*/
_hasCartChange: function () {
//$('.sc-cart-count', this.cart_element).text(this.cart.length);
$('.sc-cart-count').text(this.cart.length);
$('.sc-cart-subtotal', this.element).text(this._getCartSubtotal());
if (this.cart.length === 0) {
$('.sc-cart-item-list', this.cart_element).empty().append($('<div class="sc-cart-empty-msg">' + this.options.lang.cartEmpty + '</div>'));
$(this.options.productContainerSelector).removeClass('sc-added-item');
$('.sc-cart-checkout, .sc-cart-clear').addClass('disabled');
// Trigger "cartEmpty" event
this._triggerEvent("cartEmpty");
} else {
$('.sc-cart-item-list > .sc-cart-empty-msg', this.cart_element).remove();
$('.sc-cart-checkout, .sc-cart-clear').removeClass('disabled');
}
// Update cart value to the cart hidden element
$('#' + this.options.resultName, this.cart_element).val(JSON.stringify(this.cart));
},
/*
* Calculates the cart subtotal
*/
_getCartSubtotal: function () {
var mi = this;
var subtotal = 0;
$.each(this.cart, function (i, p) {
if (mi._getValidateNumber(p[mi.options.paramSettings.productPrice])) {
subtotal += (p[mi.options.paramSettings.productPrice] - 0) * (p[mi.options.paramSettings.productQuantity] - 0);
}
});
return this._getMoneyFormatted(subtotal);
},
/*
* Cart submit functionalities
*/
_submitCart: function () {
var mi = this;
var formElm = this.cart_element.parents('form');
if (!formElm) {
this._logError('Form not found to submit');
return false;
}
switch (this.options.submitSettings.submitType) {
case 'ajax':
var ajaxURL = this.options.submitSettings.ajaxURL && this.options.submitSettings.ajaxURL.length > 0 ? this.options.submitSettings.ajaxURL : formElm.attr('action');
var ajaxSettings = $.extend(true, {}, {
url: ajaxURL,
type: "POST",
data: formElm.serialize(),
beforeSend: function () {
mi.cart_element.addClass('loading');
},
error: function (jqXHR, status, message) {
mi.cart_element.removeClass('loading');
mi._logError(message);
},
success: function (res) {
mi.cart_element.removeClass('loading');
mi._triggerEvent("cartSubmitted", [mi.cart]);
mi._clearCart();
}
}, this.options.submitSettings.ajaxSettings);
$.ajax(ajaxSettings);
break;
case 'paypal':
formElm.children('.sc-paypal-input').remove();
// Add paypal specific fields for cart products
$.each(this.cart, function (i, p) {
var itemNumber = i + 1;
formElm.append('<input class="sc-paypal-input" name="item_number_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productId]) + '" type="hidden">').append('<input class="sc-paypal-input" name="item_name_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productName]) + '" type="hidden">').append('<input class="sc-paypal-input" name="amount_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productPrice]) + '" type="hidden">').append('<input class="sc-paypal-input" name="quantity_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productQuantity]) + '" type="hidden">');
});
formElm.submit();
this._triggerEvent("cartSubmitted", [this.cart]);
break;
default:
formElm.submit();
this._triggerEvent("cartSubmitted", [this.cart]);
break;
}
return true;
},
// HELPER FUNCTIONS
/*
* Get the content of an HTML element irrespective of its type
*/
_getContent: function (elm) {
if (elm.is(":checkbox, :radio")) {
return elm.is(":checked") ? elm.val() : '';
} else if (elm.is("[value], select")) {
return elm.val();
} else if (elm.is("img")) {
return elm.attr('src');
} else {
return elm.text();
}
return '';
},
/*
* Compare equality of two product objects
*/
_isObjectsEqual: function (o1, o2) {
if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) {
return false;
}
for (var p in o1) {
if (p === 'unique_key' || p === this.options.paramSettings.productQuantity) {
continue;
}
if (typeof o1[p] === typeof undefined && typeof o2[p] === typeof undefined) {
continue;
}
if (o1[p] !== o2[p]) {
return false;
}
}
return true;
},
/*
* Format money
*/
_getMoneyFormatted: function (n) {
n = n - 0;
return Number(n.toFixed(2)).toLocaleString(this.options.currencySettings.locales, this.options.currencySettings.currencyOptions);
},
/*
* Get the value of an element and empty value if the element not exists
*/
_getValueOrEmpty: function (v) {
return v && typeof v !== typeof undefined ? v : '';
},
/*
* Validate Number
*/
_getValidateNumber: function (n) {
n = n - 0;
if (n && n > 0) {
return true;
}
return false;
},
/*
* Small templating function
*/
_formatTemplate: function (t, o) {
var r = t.split("{"),
fs = '';
for (var i = 0; i < r.length; i++) {
var vr = r[i].substring(0, r[i].indexOf("}"));
if (vr.length > 0) {
fs += r[i].replace(vr + '}', this._getValueOrEmpty(o[vr]));
} else {
fs += r[i];
}
}
return fs;
},
/*
* Event raiser
*/
_triggerEvent: function (name, params) {
// Trigger an event
var e = $.Event(name);
this.cart_element.trigger(e, params);
if (e.isDefaultPrevented()) {
return false;
}
return e.result;
},
/*
* Get unique key
*/
_getUniqueKey: function () {
var d = new Date();
return d.getTime();
},
/*
* Log message to console
*/
_logMessage: function (msg) {
if (this.options.debug !== true) {
return false;
}
// Log message
console.log(msg);
},
/*
* Log error to console and terminate execution
*/
_logError: function (msg) {
if (this.options.debug !== true) {
return false;
}
// Log error
$.error(msg);
},
// PUBLIC FUNCTIONS
/*
* Public function to sumbit the cart
*/
submit: function () {
this._submitCart();
},
/*
* Public function to clear the cart
*/
clear: function () {
this._clearCart();
}
});
// Wrapper for the plugin
$.fn.smartCart = function (options) {
var args = arguments;
var instance;
if (options === undefined || typeof options === 'object') {
return this.each(function () {
if (!$.data(this, "smartCart")) {
$.data(this, "smartCart", new SmartCart(this, options));
}
});
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
instance = $.data(this[0], 'smartCart');
if (options === 'destroy') {
$.data(this, 'smartCart', null);
}
if (instance instanceof SmartCart && typeof instance[options] === 'function') {
return instance[options].apply(instance, Array.prototype.slice.call(args, 1));
} else {
return this;
}
}
};
})(jQuery, window, document);
Take it here: https://pastebin.com/XNuWGKcW
/*!
* jQuery Smart Cart v3.0.1
* The smart interactive jQuery Shopping Cart plugin with PayPal payment support
* http://www.techlaboratory.net/smartcart
*
* Created by Dipu Raj
* http://dipuraj.me
*
* Licensed under the terms of the MIT License
* https://github.com/techlab/SmartCart/blob/master/LICENSE
*/
;(function ($, window, document, undefined) {
"use strict";
// Default options
var defaults = {
cart: [], // initial products on cart
resultName: 'cart_list', // Submit name of the cart parameter
theme: 'default', // theme for the cart, related css need to include for other than default theme
combineProducts: true, // combine similar products on cart
highlightEffect: true, // highlight effect on adding/updating product in cart
cartItemTemplate: '<img class="img-responsive pull-left" src="{product_image}" /><h4 class="list-group-item-heading">{product_name}</h4><p class="list-group-item-text">{product_desc}</p>',
cartItemQtyTemplate: '{display_price} × {display_quantity} = {display_amount}',
productContainerSelector: '.sc-product-item',
productElementSelector: '*', // input, textarea, select, div, p
addCartSelector: '.sc-add-to-cart',
paramSettings : { // Map the paramters
productPrice: 'product_price',
productQuantity: 'product_quantity',
productName: 'product_name',
productId: 'product_id',
},
lang: { // Language variables
cartTitle: "Shopping Cart",
checkout: 'Checkout',
clear: 'Clear',
subtotal: 'Subtotal:',
cartRemove:'×',
cartEmpty: 'Cart is Empty!<br />Choose your products'
},
submitSettings: {
submitType: 'form', // form, paypal, ajax
ajaxURL: '', // Ajax submit URL
ajaxSettings: {} // Ajax extra settings for submit call
},
currencySettings: {
locales: 'en-US', // A string with a BCP 47 language tag, or an array of such strings
currencyOptions: {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol'
} // extra settings for the currency formatter. Refer: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
},
toolbarSettings: {
showToolbar: true,
showCheckoutButton: true,
showClearButton: true,
showCartSummary:true,
checkoutButtonStyle: 'default', // default, paypal, image
checkoutButtonImage: '', // image for the checkout button
toolbarExtraButtons: [] // Extra buttons to show on toolbar, array of jQuery input/buttons elements
},
debug: false
};
// The plugin constructor
function SmartCart(element, options) {
// Merge user settings with default, recursively
this.options = $.extend(true, {}, defaults, options);
// Cart array
this.cart = [];
// Cart element
this.cart_element = $(element);
// Call initial method
this.init();
}
$.extend(SmartCart.prototype, {
init: function () {
// Set the elements
this._setElements();
// Add toolbar
this._setToolbar();
// Assign plugin events
this._setEvents();
// Set initial products
var mi = this;
var stor=localStorage.getItem('cart');
if(stor!==null)
{
var load = $.parseJSON(stor);
$.each( load, function( i, n ) {
mi._addToCart(n,false);
});
}
$(this.options.cart).each(function(i, p) {
p = mi._addToCart(p);
});
// Call UI sync
this._hasCartChange();
},
// PRIVATE FUNCTIONS
/*
* Set basic elements for the cart
*/
_setElements: function () {
// The element store all cart data and submit with form
var cartListElement = $('<input type="hidden" name="' + this.options.resultName + '" id="' + this.options.resultName + '" />');
this.cart_element.append(cartListElement);
// Set the cart main element
this.cart_element.addClass('panel panel-default sc-cart sc-theme-' + this.options.theme);
this.cart_element.append('<div class="panel-heading sc-cart-heading">' + this.options.lang.cartTitle + ' <span class="sc-cart-count badge">0</span></div>');
this.cart_element.append('<div class="list-group sc-cart-item-list"></div>');
},
/*
* Set the toolbar for the cart
*/
_setToolbar: function () {
if(this.options.toolbarSettings.showToolbar !== true) { return false; }
var toolbar = $('<div></div>').addClass('panel-footer sc-toolbar');
var toolbarButtonPanel = $('<div class="sc-cart-toolbar">');
var toolbarSummaryPanel = $('<div class="sc-cart-summary">');
// Checkout Button
if(this.options.toolbarSettings.showCheckoutButton){
var btnCheckout = '';
switch(this.options.toolbarSettings.checkoutButtonStyle){
case 'paypal':
btnCheckout = '<button class="sc-button-checkout-paypal sc-cart-checkout" type="submit"><img src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/checkout-logo-medium.png" alt="Check out with PayPal" /></button>';
break;
case 'image':
btnCheckout = '<button class="sc-button-checkout-paypal sc-cart-checkout" type="submit"><img src="'+this.options.toolbarSettings.checkoutButtonImage+'" alt="Check out" /></button>';
break;
default:
btnCheckout = '<button class="btn btn-info sc-cart-checkout" type="button">' + this.options.lang.checkout + '</button> ';
break;
}
toolbarButtonPanel.append(btnCheckout);
}
// Clear Button
if(this.options.toolbarSettings.showClearButton){
var btnClear = $('<button class="btn btn-danger sc-cart-clear" type="button">').text(this.options.lang.clear);
toolbarButtonPanel.append(btnClear);
}
// Add extra toolbar buttons
if(this.options.toolbarSettings.toolbarExtraButtons && this.options.toolbarSettings.toolbarExtraButtons.length > 0){
toolbarButtonPanel.append(this.options.toolbarSettings.toolbarExtraButtons);
}
// Cart Summary
if(this.options.toolbarSettings.showCartSummary){
var panelSubTotal = $('<div class="sc-cart-summary-subtotal">');
panelSubTotal.append(this.options.lang.subtotal).append(' <span class="sc-cart-subtotal">0</span>');
toolbarSummaryPanel.append(panelSubTotal);
}
toolbar.append(toolbarSummaryPanel);
toolbar.append(toolbarButtonPanel);
this.cart_element.append(toolbar);
},
/*
* Set events for the cart
*/
_setEvents: function () {
var mi = this;
// Capture add to cart button events
$(this.options.addCartSelector).on( "click", function(e) {
e.preventDefault();
var p = mi._getProductDetails($(this));
p = mi._addToCart(p);
$(this).parents(mi.options.productContainerSelector).addClass('sc-added-item').attr('data-product-unique-key', p.unique_key);
});
// Item remove event
$(this.cart_element).on( "click", '.sc-cart-remove', function(e) {
e.preventDefault();
$(this).parents('.sc-cart-item').fadeOut( "normal", function() {
mi._removeFromCart($(this).data('unique-key'));
$(this).remove();
mi._hasCartChange();
});
});
// Item quantity change event
$(this.cart_element).on( "change", '.sc-cart-item-qty', function(e) {
e.preventDefault();
mi._updateCartQuantity($(this).parents('.sc-cart-item').data('unique-key'), $(this).val());
});
// Cart checkout event
$(this.cart_element).on( "click", '.sc-cart-checkout', function(e) {
if($(this).hasClass('disabled')) { return false; }
e.preventDefault();
mi._submitCart();
});
// Cart clear event
$(this.cart_element).on( "click", '.sc-cart-clear', function(e) {
if($(this).hasClass('disabled')) { return false; }
e.preventDefault();
$('.sc-cart-item-list > .sc-cart-item', this.cart_element).fadeOut( "normal", function() {
$(this).remove();
mi._clearCart();
mi._hasCartChange();
});
});
},
/*
* Get the parameters of a product by seaching elements with name attribute/data.
* Product details will be return as an object
*/
_getProductDetails: function (elm) {
var mi = this;
var p = {};
elm.parents(this.options.productContainerSelector)
.find(this.options.productElementSelector)
.each(function() {
if ($(this).is('[name]') === true || typeof $(this).data('name') !== typeof undefined) {
var key = $(this).attr('name') ? $(this).attr('name') : $(this).data('name');
var val = mi._getContent($(this));
if(key && val){
p[key] = val;
}
}
});
return p;
},
/*
* Add the product object to the cart
*/
_addToCart: function (p,store) {
var mi = this;
store = typeof store !== 'undefined' ? store : true;
if (!p.hasOwnProperty(this.options.paramSettings.productPrice)) {
this._logError('Price is not set for the item');
return false;
}
if (!p.hasOwnProperty(this.options.paramSettings.productQuantity)) {
this._logMessage('Quantity not found, default to 1');
p[this.options.paramSettings.productQuantity] = 1;
}
if (!p.hasOwnProperty('unique_key')) {
p.unique_key = this._getUniqueKey();
}
if(this.options.combineProducts){
var pf = $.grep(this.cart, function(n, i){
return mi._isObjectsEqual(n, p);
});
if(pf.length > 0){
var idx = this.cart.indexOf(pf[0]);
this.cart[idx][this.options.paramSettings.productQuantity] = (this.cart[idx][this.options.paramSettings.productQuantity] - 0) + (p[this.options.paramSettings.productQuantity] - 0);
p = this.cart[idx];
// Trigger "itemUpdated" event
this._triggerEvent("itemUpdated", [p]);
}else{
this.cart.push(p);
// Trigger "itemAdded" event
this._triggerEvent("itemAdded", [p]);
}
}else{
this.cart.push(p);
// Trigger "itemAdded" event
this._triggerEvent("itemAdded", [p]);
}
this._addUpdateCartItem(p);
if(store)
localStorage.setItem('cart', JSON.stringify(this.cart));
return p;
},
/*
* Remove the product object from the cart
*/
_removeFromCart: function (unique_key) {
var mi = this;
$.each( this.cart, function( i, n ) {
if(n.unique_key === unique_key){
var itemRemove = mi.cart[i];
mi.cart.splice(i, 1);
$('*[data-product-unique-key="' + unique_key + '"]').removeClass('sc-added-item');
mi._hasCartChange();
// Trigger "itemRemoved" event
this._triggerEvent("itemRemoved", [itemRemove]);
return false;
}
});
localStorage.setItem('cart', JSON.stringify(this.cart));
},
/*
* Clear all products from the cart
*/
_clearCart: function () {
this.cart = [];
// Trigger "cartCleared" event
this._triggerEvent("cartCleared");
this._hasCartChange();
},
/*
* Update the quantity of an item in the cart
*/
_updateCartQuantity: function (unique_key, qty) {
var mi = this;
var qv = this._getValidateNumber(qty);
$.each( this.cart, function( i, n ) {
if(n.unique_key === unique_key){
if(qv){
mi.cart[i][mi.options.paramSettings.productQuantity] = qty;
}
mi._addUpdateCartItem(mi.cart[i]);
// Trigger "quantityUpdate" event
this._triggerEvent("quantityUpdated", [mi.cart[i], qty]);
return false;
}
});
},
/*
* Update the UI of the cart list
*/
_addUpdateCartItem: function (p) {
var productAmount = (p[this.options.paramSettings.productQuantity] - 0) * (p[this.options.paramSettings.productPrice] - 0);
var cartList = $('.sc-cart-item-list',this.cart_element);
var elmMain = cartList.find("[data-unique-key='" + p.unique_key + "']");
if(elmMain && elmMain.length > 0){
elmMain.find(".sc-cart-item-qty").val(p[this.options.paramSettings.productQuantity]);
elmMain.find(".sc-cart-item-amount").text(this._getMoneyFormatted(productAmount));
}else{
elmMain = $('<div></div>').addClass('sc-cart-item list-group-item');
elmMain.append('<button type="button" class="sc-cart-remove">' + this.options.lang.cartRemove + '</button>');
elmMain.attr('data-unique-key', p.unique_key);
elmMain.append(this._formatTemplate(this.options.cartItemTemplate, p));
var itemSummary = '<div class="sc-cart-item-summary"><span class="sc-cart-item-price">' + this._getMoneyFormatted(p[this.options.paramSettings.productPrice]) + '</span>';
itemSummary += ' × <input type="number" min="1" max="1000" class="sc-cart-item-qty" value="' + this._getValueOrEmpty(p[this.options.paramSettings.productQuantity]) + '" />';
itemSummary += ' = <span class="sc-cart-item-amount">' + this._getMoneyFormatted(productAmount) + '</span></div>';
elmMain.append(itemSummary);
cartList.append(elmMain);
}
// Apply the highlight effect
if(this.options.highlightEffect === true){
elmMain.addClass('sc-highlight');
setTimeout(function() {
elmMain.removeClass('sc-highlight');
},500);
}
this._hasCartChange();
},
/*
* Handles the changes in the cart
*/
_hasCartChange: function () {
$('.sc-cart-count',this.cart_element).text(this.cart.length);
$('.sc-cart-subtotal',this.element).text(this._getCartSubtotal());
if(this.cart.length === 0){
$('.sc-cart-item-list',this.cart_element).empty().append($('<div class="sc-cart-empty-msg">' + this.options.lang.cartEmpty + '</div>'));
$(this.options.productContainerSelector).removeClass('sc-added-item');
$('.sc-cart-checkout, .sc-cart-clear').addClass('disabled');
// Trigger "cartEmpty" event
this._triggerEvent("cartEmpty");
}else{
$('.sc-cart-item-list > .sc-cart-empty-msg',this.cart_element).remove();
$('.sc-cart-checkout, .sc-cart-clear').removeClass('disabled');
}
// Update cart value to the cart hidden element
$('#' + this.options.resultName, this.cart_element).val(JSON.stringify(this.cart));
},
/*
* Calculates the cart subtotal
*/
_getCartSubtotal: function () {
var mi = this;
var subtotal = 0;
$.each(this.cart, function( i, p ) {
if(mi._getValidateNumber(p[mi.options.paramSettings.productPrice])){
subtotal += (p[mi.options.paramSettings.productPrice] - 0) * (p[mi.options.paramSettings.productQuantity] - 0);
}
});
return this._getMoneyFormatted(subtotal);
},
/*
* Cart submit functionalities
*/
_submitCart: function () {
var mi = this;
var formElm = this.cart_element.parents('form');
if(!formElm){
this._logError( 'Form not found to submit' );
return false;
}
switch(this.options.submitSettings.submitType){
case 'ajax':
var ajaxURL = (this.options.submitSettings.ajaxURL && this.options.submitSettings.ajaxURL.length > 0) ? this.options.submitSettings.ajaxURL : formElm.attr( 'action' );
var ajaxSettings = $.extend(true, {}, {
url: ajaxURL,
type: "POST",
data: formElm.serialize(),
beforeSend: function(){
mi.cart_element.addClass('loading');
},
error: function(jqXHR, status, message){
mi.cart_element.removeClass('loading');
mi._logError(message);
},
success: function(res){
mi.cart_element.removeClass('loading');
mi._triggerEvent("cartSubmitted", [mi.cart]);
mi._clearCart();
}
}, this.options.submitSettings.ajaxSettings);
$.ajax(ajaxSettings);
break;
case 'paypal':
formElm.children('.sc-paypal-input').remove();
// Add paypal specific fields for cart products
$.each(this.cart, function( i, p ) {
var itemNumber = i + 1;
formElm.append('<input class="sc-paypal-input" name="item_number_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productId]) + '" type="hidden">')
.append('<input class="sc-paypal-input" name="item_name_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productName]) + '" type="hidden">')
.append('<input class="sc-paypal-input" name="amount_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productPrice]) + '" type="hidden">')
.append('<input class="sc-paypal-input" name="quantity_' + itemNumber + '" value="' + mi._getValueOrEmpty(p[mi.options.paramSettings.productQuantity]) + '" type="hidden">');
});
formElm.submit();
this._triggerEvent("cartSubmitted", [this.cart]);
break;
default:
formElm.submit();
this._triggerEvent("cartSubmitted", [this.cart]);
break;
}
return true;
},
// HELPER FUNCTIONS
/*
* Get the content of an HTML element irrespective of its type
*/
_getContent: function (elm) {
if(elm.is(":checkbox, :radio")){
return elm.is(":checked") ? elm.val() : '';
} else if (elm.is("[value], select")){
return elm.val();
} else if (elm.is("img")){
return elm.attr('src');
} else {
return elm.text();
}
return '';
},
/*
* Compare equality of two product objects
*/
_isObjectsEqual: function (o1, o2) {
if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) {
return false;
}
for (var p in o1) {
if(p === 'unique_key' || p === this.options.paramSettings.productQuantity) {
continue;
}
if (typeof o1[p] === typeof undefined && typeof o2[p] === typeof undefined) {
continue;
}
if (o1[p] !== o2[p]){
return false;
}
}
return true;
},
/*
* Format money
*/
_getMoneyFormatted: function (n) {
n = n - 0;
return Number(n.toFixed(2)).toLocaleString(this.options.currencySettings.locales, this.options.currencySettings.currencyOptions);
},
/*
* Get the value of an element and empty value if the element not exists
*/
_getValueOrEmpty: function (v) {
return (v && typeof v !== typeof undefined) ? v : '';
},
/*
* Validate Number
*/
_getValidateNumber: function (n) {
n = n - 0;
if(n && n > 0){
return true;
}
return false;
},
/*
* Small templating function
*/
_formatTemplate: function (t, o){
var r = t.split("{"), fs = '';
for(var i=0; i < r.length; i++){
var vr = r[i].substring(0, r[i].indexOf("}"));
if(vr.length > 0){
fs += r[i].replace(vr + '}', this._getValueOrEmpty(o[vr]));
}else{
fs += r[i];
}
}
return fs;
},
/*
* Event raiser
*/
_triggerEvent: function (name, params) {
// Trigger an event
var e = $.Event(name);
this.cart_element.trigger(e, params);
if (e.isDefaultPrevented()) { return false; }
return e.result;
},
/*
* Get unique key
*/
_getUniqueKey: function () {
var d = new Date();
return d.getTime();
},
/*
* Log message to console
*/
_logMessage: function (msg) {
if(this.options.debug !== true) { return false; }
// Log message
console.log(msg);
},
/*
* Log error to console and terminate execution
*/
_logError: function (msg) {
if(this.options.debug !== true) { return false; }
// Log error
$.error(msg);
},
// PUBLIC FUNCTIONS
/*
* Public function to sumbit the cart
*/
submit: function () {
this._submitCart();
},
/*
* Public function to clear the cart
*/
clear: function () {
this._clearCart();
}
});
// Wrapper for the plugin
$.fn.smartCart = function(options) {
var args = arguments;
var instance;
if (options === undefined || typeof options === 'object') {
return this.each( function() {
if ( !$.data( this, "smartCart") ) {
$.data( this, "smartCart", new SmartCart( this, options ) );
}
});
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
instance = $.data(this[0], 'smartCart');
if (options === 'destroy') {
$.data(this, 'smartCart', null);
}
if (instance instanceof SmartCart && typeof instance[options] === 'function') {
return instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
} else {
return this;
}
}
};
})(jQuery, window, document);
I did it with original index.html codes.
but added cart items green checkbox top right corner removing in my side when I page refresh did you have this problem?And when I press clear button items cleared but if I page refresh they come back.
i fixed problems except card items can not empty :)
Add this line to _clearCart function: localStorage.setItem('cart', JSON.stringify(this.cart));
Thank you, Clear button working now.
What about cartRemove: '×', sign? if I press X in cart items, then if I refresh page its come back, nothing removed.
Hi guys... First and foremost I'm sorry because I'm really new to javascript / JSON and I'm french which totally null in English. ;) Thank you very much for this code and these contributions. I just spent some time trying things to change some things that did not work too much:
By doing collages of localStorage.setItem ('cart', JSON.stringify (this.cart));
at different places in the code, I think I have managed to solve these points.
For information :
<a href="index.html"> back </a>
in the file "results.php" - It allowed me to easily navigate between pages "index.html" and "results.php".. $ ( '. Sc-cart-count') text (this.cart.length);
because I'm going to need 'cart-lenght' in my future NavBar - maybe it can help some coders just by adding a div with Sc-cart-count
class in other place in "index.html" page or other pages.this._triggerEvent ("itemRemoved", [itemRemove]);
by
mi._triggerEvent ("itemRemoved", [itemRemove]);
I no longer have the error in the console.Thanks again to Dipu Raj and www.techlaboratory.net for his superb code that totally meets my needs. Here is your code with my contribution hoping not to have made mistakes and that it can serve you : https://gist.github.com/manudivallo/98bdb018fab3023b2c641afac7094e3e
Thank you all for your contributions and ideas. I'm glad that the project is useful to many peers. I will add the cart local storage option in the coming versions.
@sanalrenk
What about cartRemove: '×', sign? if I press X in cart items, then if I refresh page its come back, nothing removed.
Add this line to _hasCartChange function:
localStorage.setItem('cart', JSON.stringify(this.cart));
I wrote to @techlab but he is not responding. I was very frustrated.
Thanks to @manudivallo very much for the modification. Sadly, the "option field" didn't work. Values are not passed to PayPal.
Here is my removal and addition to the code to make the 'thing' work.
Replace this:
<label>Size: </label>
<select name="product_size" class="form-control input-sm">
<option>S</option>
<option>M</option>
<option>L</option>
</select>
with this:
<input type="hidden" name="on0" value="Size" />Size
<select name="os0">
<option value="Small">Small</option>
<option value="Medium">Medium</option>
<option value="Large">Large</option>
</select>
Add these under "paramSettings':
productSizeT: 'on0',
productSize: 'os0',
And add these to the 'append' part:
.append('<input name="on0_'+itemNumber+'" value="'+mi._getValueOrEmpty(p[mi.options.paramSettings.productSizeT])+'" type="hidden" />')
.append('<input name="os0_'+itemNumber+'" value="'+mi._getValueOrEmpty(p[mi.options.paramSettings.productSize])+'" type="hidden" />')
productSizeT and productSize can be any names you like.
My question is, how can I make option_select and option_amount work? I fail to make it happen. The amount is always showing the fixed amount as specified in <input name="product_price" value="2990.50" type="hidden" />
I used PayPal's own button factory to create a sample of drop down/option menu. I noticed the "amount" is not there. So, I presume the price must be from option_amount. I tried taking the value out, made it 0.00, took out the entire string of "amount" in the 'append' section, made it a plus somewhere and everywhere, etc. All to no avail. I realised that there are two ways that PayPal takes in parameters. I know I sound like a n00b, because I am! Hahaha!
I hope somebody here knows what I am talking about and hopefully show the coding and instruction how to do it.
Hi. Is there any way to save cart contents with cookies/localstorage when you navigate through pages?