/**************************************************************************** Copyright (c) 2009 The Wojo Group thewojogroup.com simplecartjs.com http://github.com/thewojogroup/simplecart-js/tree/master https://code.google.com/p/jscart/ The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ var NextId=1,Custom="Custom",GoogleCheckout="GoogleCheckout",PayPal="PayPal",Email="Email",AustralianDollar=AUD="AUD",CanadianDollar=CAD="CAD",CzechKoruna=CZK="CZK",DanishKrone=DKK="DKK",Euro=EUR="EUR",HongKongDollar=HKD="HKD",HungarianForint=HUF="HUF",IsraeliNewSheqel=ILS="ILS",JapaneseYen=JPY="JPY",MexicanPeso=MXN="MXN",NorwegianKrone=NOK="NOK",NewZealandDollar=NZD="NZD",PolishZloty=PLN="PLN",PoundSterling=GBP="GBP",SingaporeDollar=SGD="SGD",SwedishKrona=SEK="SEK",SwissFranc=CHF="CHF",USDollar=USD="USD"; function Cart(){ var me = this; /* member variables */ me.Version = '2.0.1'; me.Shelf = new Shelf(); me.items = {}; me.isLoaded = false; me.pageIsReady = false; me.quantity = 0; me.total = 0; me.taxRate = 0; me.taxCost = 0; me.shippingFlatRate = 0; me.shippingTotalRate = 0; me.shippingQuantityRate = 0; me.shippingRate = 0; me.shippingCost = 0; me.currency = USD; me.checkoutTo = PayPal; me.email = ""; me.merchantId = ""; me.cartHeaders = ['Name','Price','Quantity','increment','Total']; me.couponcode = 0; me.collection = 0; /* cart headers: you can set these to which ever order you would like, and the cart will display the appropriate headers and item info. any field you have for the items in the cart can be used, and 'Total' will automatically be price*quantity. there are keywords that can be used: 1) "_input" - the field will be a text input with the value set to the given field. when the user changes the value, it will update the cart. this can be useful for quantity. (ie "Quantity_input") 2) "increment" - a link with "+" that will increase the item quantity by 1 3) "decrement" - a link with "-" that will decrease the item quantity by 1 4) "remove" - a link that will remove the item from the cart 5) "_image" or "Image" - the field will be an img tag with the src set to the value. You can simply use "Image" if you set a field in the items called "Image". If you have a field named something else, like "Thumb", you can add the "_image" to create the image tag (ie "Thumb_image"). 6) "_noHeader" - this will skip the header for that field (ie "increment_noHeader") */ /****************************************************** add/remove items to cart ******************************************************/ me.add = function () { var me=this; /* load cart values if not already loaded */ if( !me.pageIsReady ) { me.initializeView(); me.update(); } if( !me.isLoaded ) { me.load(); me.update(); } var newItem = new CartItem(); /* check to ensure arguments have been passed in */ if( !arguments || arguments.length === 0 ){ error( 'No values passed for item.'); return; } var argumentArray = arguments; if( arguments[0] && typeof( arguments[0] ) != 'string' && typeof( arguments[0] ) != 'number' ){ argumentArray = arguments[0]; } newItem.parseValuesFromArray( argumentArray ); newItem.checkQuantityAndPrice(); /* if the item already exists, update the quantity */ if( me.hasItem(newItem) ) { var id=me.hasItem(newItem); me.items[id].quantity= parseInt(me.items[id].quantity,10) + parseInt(newItem.quantity,10); } else { me.items[newItem.id] = newItem; } me.update(); }; me.remove = function( id ){ var tempArray = {}; for( var item in this.items ){ if( item != id ){ tempArray[item] = this.items[item]; } } this.items = tempArray; }; me.empty = function () { bootbox.confirm("Are you sure you want to empty your cart?", function(result) { if (result) { simpleCart.items = {}; simpleCart.update(); } }) }; /****************************************************** item accessor functions ******************************************************/ me.find = function (criteria) { if( !criteria ) return null; var results = []; for( var next in me.items ){ var item = me.items[next], fits = true; for( var name in criteria ){ if( !item[name] || item[name] != criteria[name] ) fits = false; } if( fits ) results.push( me.next ) } return (results.length == 0 ) ? null : results; } /****************************************************** checkout management ******************************************************/ me.checkout = function(callback) { var message = ""; for( var current in me.items ){ var item = me.items[current]; var type = typemap[item.name].name; var name = item.option; var quantity = item.quantity; var available = parseInt(item.available); if (quantity > available) { message += "item: "+item.name+" with option: "+item.option+" has only "+available+" available.
"; } } if (message.length > 0) { callback(message); return; } simpleCart.paypalCheckout(callback); }; me.checkout2 = function(callback) { var message = ""; for( var current in me.items ){ var item = me.items[current]; var type = typemap[item.name].name; var name = item.option; var quantity = item.quantity; var available = parseInt(item.available); if (quantity > available) { message += "item: "+item.name+" with option: "+item.option+" has only "+available+" available.
"; } } if (message.length > 0) { callback(message); return; } simpleCart.paypalCheckout2(callback); }; me.paypalCheckout2 = function(callback) { var me = this, counter = 1 var pyItems = []; for( var current in me.items ){ var item = me.items[current]; var pyItem = { type: item.name, quantity: item.quantity, name: item.option }; pyItems.push(pyItem); counter++; } me.shipping(); var orderId = me.userId; jQuery.ajax({ url: "/store/order/reserve", method: "POST", data: { items: JSON.stringify(pyItems), orderId: orderId }, success: function () { // simpleCart.empty(); window.location = "/pay_paypal.html"; }, error: function(xhr, status, error) { callback(xhr.responseText); // no send to paypal } }); } me.paypalCheckout = function(callback) { var me = this, winpar = "scrollbars,location,resizable,status,width=800,height=600", strn = "https://www.paypal.com/cgi-bin/webscr?cmd=_cart" + "&upload=1" + "&business=" + me.email + "¤cy_code=" + me.currency, counter = 1, itemsString = ""; if( me.taxRate ){ strn = strn + "&tax_cart=" + me.currencyStringForPaypalCheckout( me.taxCost ); } var pyItems = []; for( var current in me.items ){ var item = me.items[current]; var pyItem = { type: item.name, quantity: item.quantity, name: item.option }; pyItems.push(pyItem); var optionsString = ""; //for( var field in item ){ // if( typeof(item[field]) != "function" && field != "id" && field != "price" && field != "quantity" && field != "name" && field != "shipping" && field != "size") { // optionsString = optionsString + ", " + field + "=" + item[field] ; // } //} //optionsString = optionsString.substring(2); optionsString = item["option"]; itemsString = itemsString + "&item_name_" + counter + "=" + item.name + "&item_number_" + counter + "=" + counter + "&quantity_" + counter + "=" + item.quantity + "&amount_" + counter + "=" + me.currencyStringForPaypalCheckout( item.price ) + "&on0_" + counter + "=" + "Options" + "&os0_" + counter + "=" + optionsString; counter++; } if( me.shipping() != 0){ itemsString = itemsString + "&item_name_" + counter + "=Shipping" + "&item_number_" + counter + "=" + counter + "&quantity_" + counter + "=1" + "&amount_" + counter + "=" + me.currencyStringForPaypalCheckout( me.shippingCost ); } strn = strn + itemsString ; var orderId = me.userId; strn += "&custom="+orderId; var origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); strn += "¬ify_url="+encodeURIComponent(origin+"/store/order/notify"); //var origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); //strn += "¬ify_url="+encodeURIComponent("http://localhost:10761/store/ipn"); jQuery.ajax({ url: "/store/order/reserve", method: "POST", data: { items: JSON.stringify(pyItems), orderId: orderId }, success: function () { //simpleCart.empty(); window.location = strn; // off to paypal }, error: function(xhr, status, error) { callback(xhr.responseText); // no send to paypal } }); }; me.googleCheckout = function() { var me = this; if( me.currency != USD && me.currency != GBP ){ error( "Google Checkout only allows the USD and GBP for currency."); return; } else if( me.merchantId === "" || me.merchantId === null || !me.merchantId ){ error( "No merchant Id for google checkout supplied."); return; } var form = document.createElement("form"), counter = 1; form.style.display = "none"; form.method = "POST"; form.action = "https://checkout.google.com/api/checkout/v2/checkoutForm/Merchant/" + me.merchantId; form.acceptCharset = "utf-8"; for( var current in me.items ){ var item = me.items[current]; form.appendChild( me.createHiddenElement( "item_name_" + counter, item.name ) ); form.appendChild( me.createHiddenElement( "item_quantity_" + counter, item.quantity ) ); form.appendChild( me.createHiddenElement( "item_price_" + counter, item.price ) ); form.appendChild( me.createHiddenElement( "item_currency_" + counter, me.currency ) ); form.appendChild( me.createHiddenElement( "item_tax_rate_" + counter, me.taxRate ) ); form.appendChild( me.createHiddenElement( "_charset_", "" ) ); var descriptionString = ""; for( var field in item){ if( typeof( item[field] ) != "function" && field != "id" && field != "quantity" && field != "price" ) { descriptionString = descriptionString + ", " + field + ": " + item[field]; } } descriptionString = descriptionString.substring( 1 ); form.appendChild( me.createHiddenElement( "item_description_" + counter, descriptionString) ); counter++; } document.body.appendChild( form ); form.submit(); document.body.removeChild( form ); }; me.emailCheckout = function() { return; }; me.customCheckout = function() { return; }; /****************************************************** data storage and retrival ******************************************************/ /* load cart from cookie */ me.load = function () { var me = this; /* initialize variables and items array */ me.items = {}; me.total = 0.00; me.quantity = 0; me.sampleBox = false; /* retrieve item data from cookie */ if( readCart('simpleCart') ){ var data = unescape(readCart('simpleCart')).split('++'); for(var x=0, xlen=data.length;x 0 ){ me.updateCartView(); } }; me.updateViewTotals = function() { var outlets = [ ["quantity" , "none" ] , ["total" , "currency" ] , ["shippingCost" , "currency" ] , ["taxCost" , "currency" ] , ["taxRate" , "percentage" ] , ["finalTotal" , "currency" ] ]; for( var x=0,xlen=outlets.length; x"; } }; me.valueToTextInput = function( value , html ){ return ""; }; me.valueToLink = function( value, link, html){ return "" + value + ""; }; me.valueToElement = function( type , value , html ){ return "<" + type + " " + html + " > " + value + ""; }; /****************************************************** Duplicate management ******************************************************/ me.hasItem = function ( item ) { for( var current in me.items ) { var testItem = me.items[current]; var matches = true; for( var field in item ){ if( typeof( item[field] ) != "function" && field != "quantity" && field != "id" ){ if( item[field] != testItem[field] ){ matches = false; } } } if( matches ){ return current; } } return false; }; /****************************************************** Cart Update managment ******************************************************/ me.update = function() { if( !simpleCart.isLoaded ){ simpleCart.load(); } if( !simpleCart.pageIsReady ){ simpleCart.initializeView(); } me.updateTotals(); me.updateView(); me.save(); }; me.updateTotals = function() { me.total = 0 ; me.quantity = 0; for( var current in me.items ){ var item = me.items[current]; if( item.quantity < 1 ){ item.remove(); } else if( item.quantity !== null && item.quantity != "undefined" ){ me.quantity = parseInt(me.quantity,10) + parseInt(item.quantity,10); } if( item.price ){ me.total = parseFloat(me.total) + parseInt(item.quantity,10)*parseFloat(item.price); } } var shippingTotal = me.shipping(); var total = me.total; if (total <= 25.00 && shippingTotal < 850) me.shippingCost = 5.90; else if (total <= 60.00 && shippingTotal < 4500) me.shippingCost = 6.50; else me.shippingCost = 12.00; me.taxCost = parseFloat(me.total)*me.taxRate; me.finalTotal = me.shippingCost + me.taxCost + me.total - me.couponcode; if (me.finalTotal <= 0) { me.finalTotal = 0; } }; me.applydiscount = function() { var ccode = document.getElementById('ccv').value; if (ccode === "abc123") { me.couponcode = 1; alert("Discount Applied"); } else { me.couponcode = 0; } document.getElementById('couponcode').innerHTML = "Discount: $" + me.couponcode.toFixed(2) + "
"; me.update(); }; me.shipping = function(){ if( parseInt(me.quantity,10)===0 ) return 0; var coll; var collection = readCart("collection") if (collection == "1") coll = 0; else coll = 1; var shipping = coll * (parseFloat(me.shippingFlatRate) + parseFloat(me.shippingTotalRate)*parseFloat(me.total) + parseFloat(me.shippingQuantityRate)*parseInt(me.quantity,10)), nextItem, next; for(next in me.items){ nextItem = me.items[next]; if( nextItem.shipping ){ if( typeof nextItem.shipping == 'function' ){ shipping += parseFloat(nextItem.shipping()); } else { shipping += parseFloat(nextItem.shipping); } } } return shipping; }; me.initialize = function() { simpleCart.initializeView(); simpleCart.load(); simpleCart.update(); }; } /******************************************************************************************************** * Cart Item Object ********************************************************************************************************/ function CartItem() { this.id = "c" + NextId++; } CartItem.prototype.set = function ( field , value ){ field = field.toLowerCase(); if( typeof( this[field] ) != "function" && field != "id" ){ if( field == "quantity" ){ value = value.replace( /[^(\d|\.)]*/gi , "" ); value = value.replace(/,*/gi, ""); value = parseInt(value,10); } else if( field == "price"){ value = value.replace( /[^(\d|\.)]*/gi, ""); value = value.replace(/,*/gi , ""); value = parseFloat( value ); } if( typeof(value) == "number" && isNaN( value ) ){ error( "Improperly formatted input."); } else { this[field] = value; this.checkQuantityAndPrice(); } } else { error( "Cannot change " + field + ", this is a reserved field."); } simpleCart.update(); }; CartItem.prototype.increment = function(){ this.quantity = parseInt(this.quantity,10) + 1; simpleCart.update(); }; CartItem.prototype.decrement = function(){ if( parseInt(this.quantity,10) < 2 ){ this.remove(); } else { this.quantity = parseInt(this.quantity,10) - 1; simpleCart.update(); } }; CartItem.prototype.print = function () { var returnString = ''; for( var field in this ) { if( typeof( this[field] ) != "function" ) { returnString+= escape(field) + "=" + escape(this[field]) + "||"; } } return returnString.substring(0,returnString.length-2); }; CartItem.prototype.checkQuantityAndPrice = function() { if( !this.price || this.quantity == null || this.quantity == 'undefined'){ this.quantity = 1; error('No quantity for item.'); } else { this.quantity = ("" + this.quantity).replace(/,*/gi, "" ); this.quantity = parseInt( ("" + this.quantity).replace( /[^(\d|\.)]*/gi, "") , 10); if( isNaN(this.quantity) ){ error('Quantity is not a number.'); this.quantity = 1; } } if( !this.price || this.price == null || this.price == 'undefined'){ this.price=0.00; error('No price for item or price not properly formatted.'); } else { this.price = ("" + this.price).replace(/,*/gi, "" ); this.price = parseFloat( ("" + this.price).replace( /[^(\d|\.)]*/gi, "") ); if( isNaN(this.price) ){ error('Price is not a number.'); this.price = 0.00; } } }; CartItem.prototype.parseValuesFromArray = function( array ) { if( array && array.length && array.length > 0) { for(var x=0, xlen=array.length; x1 ){ if( value.length>2 ){ for(var j=2, jlen=value.length;j available) { alert("Sorry, there are not enough items available"); } else { simpleCart.Shelf.items[id].addToCart(); jQuery("#added").css( { top: jQuery(this).position().top - 18, left: jQuery(this).position().left}).show().delay(1000).fadeOut(); } } else { error( "Shelf item with id of " + id + " does not exist."); } }; }; /******************************************************************************************************** * Shelf Item Object ********************************************************************************************************/ function ShelfItem(){ this.id = "s" + NextId++; } ShelfItem.prototype.remove = function () { simpleCart.Shelf.items[this.id] = null; }; ShelfItem.prototype.addToCart = function () { var outStrings = [],valueString; for( var field in this ){ if( typeof( this[field] ) != "function" && field != "id" ){ valueString = ""; switch(field){ case "price": if( this[field].value ){ valueString = this[field].value; } else if( this[field].innerHTML ) { valueString = this[field].innerHTML; } /* remove all characters from price except digits and a period */ valueString = valueString.replace( /[^(\d|\.)]*/gi , "" ); valueString = valueString.replace( /,*/ , "" ); break; case "image": valueString = this[field].src; break; default: if( this[field].value ){ valueString = this[field].value; } else if( this[field].innerHTML ) { valueString = this[field].innerHTML; } else if( this[field].src ){ valueString = this[field].src; } else { valueString = this[field]; } break; } outStrings.push( field + "=" + valueString ); } } simpleCart.add( outStrings ); }; /******************************************************************************************************** * Thanks to Peter-Paul Koch for these cookie functions (http://www.quirksmode.org/js/cookies.html) ********************************************************************************************************/ function createCookie(name,value,days) { var expires; if (days) { var date = new Date(); date.setTime(date.getTime()+(days*24*60*60*1000)); expires = "; expires="+date.toGMTString(); } else expires = ""; document.cookie = name+"="+value+expires+"; path=/"; } function readCart(name) { if (!!localStorage) { return localStorage.getItem('simpleCart:'+name); } else { return readCookie(name); } } function storeCart(name,value,days) { if (!!localStorage) { return localStorage.setItem('simpleCart:'+name,value); } else { return createCookie(name,value,days); } } function readCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length); } return null; } function eraseCookie(name) { storeCart(name,"",-1); } //************************************************************************************************* /* Developed by Robert Nyman, http://www.robertnyman.com Code/licensing: http://code.google.com/p/getelementsbyclassname/ */ var getElementsByClassName = function (className, tag, elm){ if (document.getElementsByClassName) { getElementsByClassName = function (className, tag, elm) { elm = elm || document; var elements = elm.getElementsByClassName(className), nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null, returnElements = [], current; for(var i=0, il=elements.length; i