An AJAX Based Shopping Cart with PHP, CSS & jQuery

An AJAX Based Shopping Cart with PHP, CSS & jQuery

Introduction

In this tutorial we are going to create an AJAX-driven shopping cart. All the products are going to be stored in a MySQL database, with PHP showing and processing the data.

jQuery will drive the AJAX-es on the page, and with the help of the simpletip plugin will add to an interactive check out process.

So go ahead, download the demo files and start reading.

Step 1 – the MySQL Database

If you want to set up a working demo, you’ll need to execute the following SQL code in your database manager (e.g. phpMyAdmin).  It will set up the table and insert a few products. The code is also available in table.sql in the demo files.

table.sql

CREATE TABLE IF NOT EXISTS `internet_shop` (
  `id` int(6) NOT NULL auto_increment,
  `img` varchar(32) collate utf8_unicode_ci NOT NULL default '',
  `name` varchar(64) collate utf8_unicode_ci NOT NULL default '',
  `description` text collate utf8_unicode_ci NOT NULL,
  `price` double NOT NULL default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `img` (`img`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ;

INSERT INTO `internet_shop` VALUES(1, 'iPod.png', 'iPod', 'The original and popular iPod.', 200);
INSERT INTO `internet_shop` VALUES(2, 'iMac.png', 'iMac', 'The iMac computer.', 1200);
INSERT INTO `internet_shop` VALUES(3, 'iPhone.png', 'iPhone', 'This is the new iPhone.', 400);
INSERT INTO `internet_shop` VALUES(4, 'iPod-Shuffle.png', 'iPod Shuffle', 'The new iPod shuffle.', 49);
INSERT INTO `internet_shop` VALUES(5, 'iPod-Nano.png', 'iPod Nano', 'The new iPod Nano.', 99);
INSERT INTO `internet_shop` VALUES(6, 'Apple-TV.png', 'Apple TV', 'The new Apple TV. Buy it now!', 300);

After this, you should fill in your MySQL credentials in connect.inc.php.

Step 2 – the XHTML

First we start off with our main markup.

demo.php

<div id="main-container"> <!-- the main container element -->

<div class="tutorialzine">	<!-- some headings -->
<h1>Shopping cart</h1>
<h3>The best products at the best prices</h3>
</div>

<div class="container">	<!-- the first section - products -->

<span class="top-label">
<span class="label-txt">Products</span>	<!-- section label -->
</span>

<div class="content-area">
<div class="content drag-desired">	<!-- assigning a common content class and an individually targeted drag-desired class -->

<?php
// php code that generates the products
?>

<div class="clear"></div>	<!-- clearing the floats -->
</div>
</div>

<div class="bottom-container-border">	<!-- bottom part of the section -->
</div>

</div>	<!-- closing the products section -->

<div class="container">	<!-- the second section - shopping cart -->

<span class="top-label">
<span class="label-txt">Shopping Cart</span>	<!-- label for the section -->
</span>

<div class="content-area">
<div class="content drop-here">	<!-- content class, shared with the product section above, and the targeted drop-here class -->
<div id="cart-icon">
<img src="img/Shoppingcart_128x128.png" alt="shopping cart" class="pngfix" width="128" height="128" />	<!-- using the pngfix class -->
<img src="img/ajax_load_2.gif" alt="loading.." id="ajax-loader" width="16" height="16" />	<!-- the rotating gif - hidden by default and shown during ajax interactions -->
</div>

<form name="checkoutForm" method="post" action="order.php">	<!-- the form -->
<div id="item-list">	<!-- in this div we insert all the products in the shopping cart -->

</div>
</form>	<!-- closing the form -->

<div class="clear"></div>	<!-- clearing -->

<div id="total"></div>	<!-- the total price goes here -->
<div class="clear"></div>	<!-- clearing the floats -->

<a href="" onclick="document.forms.checkoutForm.submit(); return false;" class="button">Checkout</a>	<!-- the submit button, hidden by default, notice the onclick attribute -->

</div>
</div>

<div class="bottom-container-border">	<!-- bottom part of the section -->
</div>

</div><!-- closing the main container -->

As you can see, we’ve organized our content into two main sections, which are almost identical in the XHTML markup they use – the first one, where all the products are displayed, and second one, acting as a shopping card.

Below you can see a detailed explanation of the structure of the product section.

The product section

The product section

The products are generated by our PHP code, as you can see on line 18. We are digging deeper into this in a few minutes. Now lets take a look at how we turned the XHTML layout into a finished design.

Step 3 – the CSS

This time the CSS code is quite long, so I’m going to split it into parts.

demo.css

body,h1,h2,h3,p,td,quote,small,form,input,ul,li,ol,label{
/* resetting some of the styles for browser compatibility */
	margin:0px;
	padding:0px;
	font-family:Arial, Helvetica, sans-serif;
}

body{
	color:#555555;
	font-size:13px;
	background-color:#282828;
}

.clear{	/* implementing the clear-fix hack for fixing floated layouts */
	clear:both;
}

#main-container{	/* this is the main container, holding the two sections */
	width:700px;
	margin:20px auto;
}

.container{	/* the main container of our content sections - the products and the shopping cart */
	margin-bottom:40px;
}

.top-label{	/* the outer span comprising the label */
	background:url(img/label_bg.png) no-repeat;	/* showing the left part of label_bg.png - a wide round-cornered image */
	display:inline-block;
	margin-left:20px;
	position:relative;
	margin-bottom:-15px;	/* the whole label is lowered on the product section */
}

.label-txt{	/* the inner span - red border in the illustration above */
	background:url(img/label_bg.png) no-repeat top right;	/* shows the right part of the wider label_bg.png */
	display:inline-block;
	font-size:10px;
	height:36px;
	margin-left:10px;	/* leaves space on the left, so that the outer span can show its background */
	padding:12px 15px 0 5px;
	text-transform:uppercase;
}

.content-area{	/* The top part of the rounded container image, see the illustration above */
	background:url(img/container_top.png) no-repeat #fcfcfc;
	padding:15px 20px 0 20px;
}

.content{	/* shared by the two sections */
	padding:10px;
}

.drag-desired{	/* individually targeted properties */
	background:url(img/drag_desired_label.png) no-repeat top right;
	padding:30px;
}

.drop-here{	/* not shared with the other sections */
	background:url(img/drop_here_label.png) no-repeat top right;
}

.bottom-container-border{	/* the bottom rounded graphic, that completes the section */
	background:url(img/container_bottom.png) no-repeat;
	height:14px;
}

.product{	/* styling the products */
	border:2px solid #F5F5F5;
	float:left;
	margin:15px;
	padding:10px;
}

.product img{
	cursor:move;
}

p.descr{
	padding:5px 0;
}

small{
	display:block;
	margin-top:4px;
}

.tooltip{	/* the tooltips, this div is created by the simpletip plugin */
	position: absolute;
	top: 0;
	left: 0;
	z-index: 3;
	display: none;

	background-color:#666666;
	border:1px solid #666666;
	color:#fcfcfc;

	padding:10px;

	-moz-border-radius:12px;	/* rounded corners */
	-khtml-border-radius: 12px;
	-webkit-border-radius: 12px;
	border-radius:12px;
}

Notice the tooltip class. It is created automatically by the simpletip plugin, but it has no styles applied by default. That is why we style it here. I’ve used the border-radius property, which is not yet supported by all browsers, but will degrade gracefully for those that don’t.

Now lets take a look at the styles that target the shopping cart section.

#cart-icon{	/* the div that contains the shopping cart icon */
	width:128px;
	float:left;
	position:relative;	/* changing the position to relative so that ajax-loader is positioned relative to it */
}

#ajax-loader{
	position:absolute;	/* absolute positioning makes an element relative to its parent if the latter has positioning different from the default  */
	top:0px;
	left:0px;
	visibility:hidden;
}

#item-list{	/* the contents of the shopping cart goes into this div */
	float:left;
	width:490px;
	margin-left:20px;
	padding-top:15px;
}

a.remove,a.remove:visited{	/* the REMOVE link */
	color:red;
	font-size:10px;
	text-transform:uppercase;
}

#total{	/* the total cost div */
	clear:both;
	float:right;
	font-size:10px;
	font-weight:bold;
	padding:10px 12px;
	text-transform:uppercase;
}

#item-list table{	/* every product in the shopping cart is positioned inside the item-list div */
	background-color:#F7F7F7;
	border:1px solid #EFEFEF;
	margin-top:5px;
	padding:4px;
}

a.button,a.button:visited{	/* the CHECKOUT button */
	display:none;

	height:29px;
	width:136px;

	padding-top:15px;
	margin:0 auto;
	overflow:hidden;

	color:white;
	font-size:12px;
	font-weight:bold;
	text-align:center;
	text-transform:uppercase;

	background:url(img/button.png) no-repeat center top;	/* showing only the top part of the background image */
}

a.button:hover{
	background-position:bottom;	/* on hover we show the bottom part of the image */
	text-decoration:none;
}

/* Some less interesting classes */

a, a:visited {
	color:#00BBFF;
	text-decoration:none;
	outline:none;
}

a:hover{
	text-decoration:underline;
}

h1{
	font-size:28px;
	font-weight:bold;
	font-family:"Trebuchet MS",Arial, Helvetica, sans-serif;
}

h2{
	font-weight:normal;
	font-size:20px;

	color:#666666;
	text-indent:30px;
	margin:20px 0;
}

.tutorialzine h1{
	color:white;
	margin-bottom:10px;
	font-size:48px;
}

.tutorialzine h3{
	color:#F5F5F5;
	font-size:10px;
	font-weight:bold;
	margin-bottom:30px;
	text-transform:uppercase;
}

.tutorial-info{
	color:white;
	text-align:center;
	padding:10px;
	margin-top:-20px;
}

As any front-end developer will tell you, we have something missing here. You guessed it – special treatment for IE6.

I personally plan to stop supporting IE6 soon in my projects altogether – if it wasn’t for it, the above code would have been at least a quarter shorter, and it would have taken a lot less time to debug.

But anyway, here is how we target IE6 specifically:

demo.php

<!--[if lt IE 7]>
<style type="text/css">
	.pngfix { behavior: url(pngfix/iepngfix.htc);}	/* this is a special htc file that fixes the IE6 transparency issues */
	.tooltip{width:200px;};	/* provide a default width for the tooltips */
</style>
<![endif]-->

There. Now lets take a look at the PHP backend.

The sopping cart

The shopping cart

Step 4 – PHP

We use PHP in a number of ways and places. First lets look at how the product list is generated on the main page.

demo.php

$result = mysql_query("SELECT * FROM internet_shop");	// selecting all the products
while($row=mysql_fetch_assoc($result))
{
	echo '<div class="product"><img src="img/products/'.$row['img'].'" alt="'.htmlspecialchars($row['name']).'" width="128" height="128" class="pngfix" /></div>';
}

Another place where we use PHP is in tips.php, which takes an image file name as a parameter, checks which product is associated with that image, and outputs the tool tip data as html. This is later used by the simpletip plugin.

ajax/tips.php

define('INCLUDE_CHECK',1);
require "../connect.php";

if(!$_POST['img']) die("There is no such product!");

$img=mysql_real_escape_string(end(explode('/',$_POST['img'])));

$row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img='".$img."'"));

if(!$row) die("There is no such product!");

echo '<strong>'.$row['name'].'</strong>
<p class="descr">'.$row['description'].'</p>
<strong>price: $'.$row['price'].'</strong>
<small>Drag it to your shopping cart to purchase it</small>';

We also use PHP to return the necessary data for the addition of products in the shopping cart. The difference is that this time we return the data as JSON (a javascript object).

ajax/addtocart.php

define('INCLUDE_CHECK',1);
require "../connect.php";

if(!$_POST['img']) die("There is no such product!");

$img=mysql_real_escape_string(end(explode('/',$_POST['img'])));
$row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img='".$img."'"));

echo '{status:1,id:'.$row['id'].',price:'.$row['price'].',txt:\'\
\
<table width="100%" id="table_'.$row['id'].'">\
<tr>\
<td width="60%">'.$row['name'].'</td>\
<td width="10%">$'.$row['price'].'</td>\
<td width="15%"><select name="'.$row['id'].'_cnt" id="'.$row['id'].'_cnt" onchange="change('.$row['id'].');">\
<option value="1">1</option>\
<option value="2">2</option>\
<option value="3">3</option></slect>\
\
</td>\
<td width="15%"><a href="#" onclick="remove('.$row['id'].');return false;" class="remove">remove</a></td>\
</tr>\
</table>\'}';

The outputted object has status, id, price and txt properties. These are used by our AJAX functions as you’ll see in a moment.

Notice how I’ve escaped each line of the string with a backslash. This is done because javascript does not support multiline strings.

The last place where we use PHP is in order.php, which is used to process the orders. Currently, it just outputs your order. You could modify it to include an email form, paypal functionality, or anything that will make it into a functional online shop.

order.php

<?php

define('INCLUDE_CHECK',1);
require "connect.php";

if(!$_POST)	// if there is no data submitted to the form
{
	if($_SERVER['HTTP_REFERER'])	// redirect
	header('Location : '.$_SERVER['HTTP_REFERER']);
	exit;	// and exit
}

?>

<!-- XHTML code.. -->

<?php

$cnt = array();
$products = array();

foreach($_POST as $key=>$value)
{
	$key=(int)str_replace('_cnt','',$key);
	$products[]=$key;	// store the product ids in an array
	$cnt[$key]=$value;	// create a key / value pair where for each product id there is a corresponding value being the number of products
 purchased}

$result = mysql_query("SELECT * FROM internet_shop WHERE id IN(".join($products,',').")");	// selecting all the products with the IN() function

if(!mysql_num_rows($result))	// no products found
{
	echo '<h1>There was an error with your order!</h1>';
}
else
{
	echo '<h1>You ordered:</h1>';
	while($row=mysql_fetch_assoc($result))
	{
		echo '<h2>'.$cnt[$row['id']].' x '.$row['name'].'</h2>';
		$total+=$cnt[$row['id']]*$row['price'];
	}

	echo '<h1>Total: $'.$total.'</h1>';
}

?>

This concludes the PHP section. The only thing that is left is some jQuery magic.

A simple order page

A simple order page

Step 5 – jQuery

We will utilize jQuery to the fullest, so we will need to include the additional jQuery UI library as well as the basic library.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="simpletip/jquery.simpletip-1.3.1.pack.js"></script> <!-- the jQuery simpletip plugin -->
<script type="text/javascript" src="script.js"></script> <!-- our script.js file -->

Now we can continue with our script.

script.js

var purchased=new Array();	//an array containing all the products we've purchased so far
var totalprice=0;	//the total price

$(document).ready(function(){

	$('.product').simpletip({	//using the simpletip plugin

		offset:[40,0],
		content:'<img style="margin:10px;" src="img/ajax_load.gif" alt="loading" />',	// default content
		onShow: function(){

			var param = this.getParent().find('img').attr('src');
			// fix for IE6
			if($.browser.msie && $.browser.version=='6.0')
			{
				param = this.getParent().find('img').attr('style').match(/src=\"([^\"]+)\"/);
				param = param[1];
			}

			// after the tooltip is shown, load the tips.php file and pass the image name as a parameter
			this.load('ajax/tips.php',{img:param});
		} 

	});

	$(".product img").draggable({	// enable all product images to be dragged

	containment: 'document',
	opacity: 0.6,
	revert: 'invalid',
	helper: 'clone',
	zIndex: 100

	});

	$("div.content.drop-here").droppable({	// convert the shopping cart to a droppable

			drop:
				function(e, ui)
				{
					var param = $(ui.draggable).attr('src');
					// IE6 fix
					if($.browser.msie && $.browser.version=='6.0')
					{
						param = $(ui.draggable).attr('style').match(/src=\"([^\"]+)\"/);
						param = param[1];
					}

					addlist(param);	// the special addlist function - see below
				}

	});

});

The main idea here is that we use an image’s src attribute as an unique key that is sent to the PHP back-end. Every product in the DB has a file name filed, which enables us to find the product by it’s product image.

This whole block of code is executed after the page has finished loading, so we are sure that all the elements on the page are initialized.

Below is the second part of script.js.

function addlist(param)
{
	// the addlist function ads a product to the shopping cart

	$.ajax({	// sending an ajax request to addtocart.php
	type: "POST",
	url: "ajax/addtocart.php",
	data: 'img='+encodeURIComponent(param),	// the product image as a parameter
	dataType: 'json',	// expecting json
	beforeSend: function(x){$('#ajax-loader').css('visibility','visible');},	// showing the loading gif
	success: function(msg){

		$('#ajax-loader').css('visibility','hidden');	// hiding the loading gif animation
		if(parseInt(msg.status)!=1)
		{
			return false;	// if there has been an error, return false
		}
		else
		{
			var check=false;
			var cnt = false;

			for(var i=0; i<purchased.length;i++)
			{
				if(purchased[i].id==msg.id)	// find if we have already bought this prduct
				{
					check=true;
					cnt=purchased[i].cnt;

					break;
				}
			}

			if(!cnt)	// if we haven't bought it yet, or we have removed it from the purchases, we insert it in the shopping cart
				$('#item-list').append(msg.txt);

			if(!check)	// if we haven't bought it yet, insert it in the purchased array
			{
				purchased.push({id:msg.id,cnt:1,price:msg.price});
			}

			else	// else if we've bought it
			{
				if(cnt>=3) return false;	// 3 products of type max

				purchased[i].cnt++;
				$('#'+msg.id+'_cnt').val(purchased[i].cnt);	// update the select box
			}

			totalprice+=msg.price;	// recalculate the price
			update_total();	// update the total div

		}

		$('.tooltip').hide();	// hiding the tooltip (sometimes it stays on screen after the drag)

	}
	});
}

function findpos(id)	// a helper function that finds the position at which the product is inserted in the array, returns the position
{
	for(var i=0; i<purchased.length;i++)
	{
		if(purchased[i].id==id)
			return i;
	}

	return false;
}

function remove(id)	// remove a product from the shopping cart
{
	var i=findpos(id);	// find its position in the array

	totalprice-=purchased[i].price*purchased[i].cnt;	// recalculate the price
	purchased[i].cnt = 0;	// reset the counter

	$('#table_'+id).remove();	// remove it from the cart
	update_total();	// update the total price counter on the page
}

function change(id)	// evoked when we change the number of products via the select area
{
	var i=findpos(id);

	totalprice+=(parseInt($('#'+id+'_cnt').val())-purchased[i].cnt)*purchased[i].price;

	purchased[i].cnt=parseInt($('#'+id+'_cnt').val());
	update_total();
}

function update_total()	// function that updates the total price div on the page
{
	if(totalprice)
	{
		$('#total').html('total: $'+totalprice);	// if we've bought somehitng, show the total price div and the purchase button
		$('a.button').css('display','block');
	}
	else	// hide them
	{
		$('#total').html('');
		$('a.button').hide();
	}
}

There are a few places in this code, where we use an id for pointing to a product. The id is a unique identifier, that is assigned by the MySQL database once we insert a new item.
It is passed by the AJAX requests and we need to translate it to the index position of our products array in order to use it, which is the purpose of the findpos() function.

With this our shopping cart is complete!

Conclusion

Today we made a functional AJAX driven shopping cart. You are free to download the code and modify it any way you wish. You can build upon it and even turn it into a full fledged online shop.

Join our newsletter and get our PSDs!19,481 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

99 Comments

  1. Great tut, love it, would be awesome to see it fully fledged with paypal etc ...

  2. mgpyone says:

    Cheer Up.. That's really gr8

  3. paul rostorp says:

    Awesome!!! thanks,

  4. Al says:

    Niiiice article! Thank you for sharing!

  5. Adeline says:

    I agree with Max! but thanks for the starting point :)

  6. Kevin says:

    I love Ajax and jQuery combination. You can do a lot of magical stuff with them... I am already using both and they are amazing...

  7. Nokadota says:

    This is pretty sweet, thanks for the tutorial.

  8. Jamie says:

    Nice in depth tut. Good work!

  9. Lukas says:

    Great and nice Shopping Cart. Thanks for the tutorial. Excelent.

  10. Graham says:

    Well done - it looks great.
    I'm sure this has the potential to become a really great platform for easy to use simple shopping carts.

  11. DavidK says:

    A shopping cart... in AJAX... with no graceful degradation for clients in which it doesn't work.

    So, who wants to trust their actual bottom line revenue to whether or not the client supports javascript and is mature enough to support all of this stuff?

    You should have a way to let people select items using basic forms and then layer on the jazz... for stuff like this to fly you cannot risk losing a customer over it.

  12. Martin says:

    Thanks to everyone for the great comments, I am pleased to see you like the tutorial.

    @ DavidK

    Thanks for the comment, David. The purpose of this article is to demonstrate what can be done with the technologies used, and how to do it.
    It is not meant to be used in a production environment.

    As you nicely put it, graceful degradation is an important factor that guarantees one is able to provide a fully working service, regardless of the visitor's browser or configuration.

    However, graceful degradation is quite an extensive subject and it would be better to leave it for another tutorial.

  13. Tom says:

    Hey there,

    why do you still use extra elements to clear? Bad practice... http://www.positioniseverything.net/easyclearing.html :)

  14. WebDevHobo says:

    Personally, I would have put the shopping cart to the left of the items, since long lists would make it a bore to drag the object all the way down.

    Other than that, nice tut.

  15. Tim says:

    Cool shopping cart tutorial!

  16. Gus says:

    Hey, your site is hot! Keep the good work!

  17. moabi says:

    very nice tut...long life to u...

  18. Jack says:

    Hey,

    Please, consider a model where you start with all zero items in the basket. Then, you add some rules - say,buy 2 items get one free, etc.
    Also, rules about totals & deliveries are also needed to make such product applicable to many shops

    Cheers,

  19. Raphi says:

    As good looking as simple really nice tut

  20. bangjak says:

    very nice! thank you

  21. Navarr says:

    I love it. But I think in a real production environment, it would be beneficial to also have it add the items to the cart on-click, as that was what felt natural and expected (instead, nothing happened when clicking an item).

    Just a note to web devs who might uses this tutorial ;)

  22. Nikolius says:

    Thanks for this great tutorial..
    just wonder, how can i keep the item list in the shopping cart when u user click to other page, or refresh the page.

    i already tried in the demo file, but when i refresh the page or click to other link the item list in the shopping cart become empty again.

    is there anyway to keep the list in the shopping cart?

  23. Martin says:

    Hello, Nikolius.

    The easy way to do this would be to add some JavaScript that stores each added item in a cookie in the visitor's browser. You can just put it in the update_total function, as it is called every time the shopping cart is changed.

    The code you'll need to add will have to reset the cookie with the id and quantity of all the products in the cart every time a product is added or removed.

    Later, in the $(document).ready section the code will populate the shopping cart with the data in the cookie - this will bring the cart in the state before the browser refresh.

  24. bassy says:

    how nice.
    thank you

  25. monika says:

    i really like this one ;)
    this site will be my favorite;))
    cool...

    hmm.. can i ask something?... because im just a 2nd year college and i'm confused... my professor is so cheap and he don't teach to us ajax clearly..
    ;(
    what's a database manager? is it like sqlyog? ;(( i hope you would reply to me quickly... LOL ;)
    and what about the connect.inc.php? and phpMyAdmin.. ;(( (so embarrassing to ask)

  26. Nano Thailand says:

    Good job.

  27. monika says:

    im really having a hard time here... i cannot connect my sqlyog database. >.< what will i put in the require "connect.php";

  28. nunoz says:

    Very good tutorial, i really like :)
    it would be nice to send the shopping cart info to email how it's possible ?

  29. Martin says:

    @ monika

    I think it would be better if you first follow some simpler tutorials about AJAX and/or MySQL. It will give you a better understanding on the subject and you'll have no problems configuring this demo.

    @ nunoz

    In the AJAX contact from tutorial ( http://tutorialzine.com/2009/09/fancy-contact-form/ ) I've used the PHP mailer class - you could include the class and put the code that sends emails in order.php.

  30. monika says:

    wee thanks anyway.. i got it ;) i was so stupid..i didn't download an apache server..;)) i was able to run all your demo..=) your site is really really good!;)

  31. janus lee says:

    i wanted to make the container of the products a content slider... how is it? martin..please help me...

  32. janus lee says:

    another thing more... is that... how can i add a "clicking" function on the product.. ? how is it possible..

  33. galechus says:

    Nice shopping cart. How add the items to the cart on-click?

  34. galechus says:

    i try something like this:
    $("#lista_produktow li a.link_produkt_dodaj").click(function() {
    var param = $("#lista_produktow li").find('img').attr('src');

    if($.browser.msie && $.browser.version=='6.0')
    {
    param = $("#lista_produktow li").find('img').attr('style').match(/src=\"([^\"]+)\"/);
    param = param[1];
    }
    addlist(param);
    });

    When click add to cart #ajax-loader show and nothing wasn't add to basket... Any suggestion?

  35. Martin says:

    @ janus lee, @ galechus

    To add a product to the shopping cart on click you'll need to add the following code in script.js (on line 53 in $(document).ready ):

    $('.product img').click(function(){

    var param = $(this).attr('src');
    if($.browser.msie && $.browser.version=='6.0')
    {
    param = $(this).attr('style').match(/src=\"([^\"]+)\"/);
    param = param[1];
    }

    addlist(param);
    });

    This will do the trick.

  36. galechus says:

    thx, but how do this on link not img.

  37. galechus says:

    ... and how make simpletip on link not on .product (li)

  38. icy says:

    Hy.. I can´t figure out how to e-mail order from cart using php.mailer class. Can anyone help me?

  39. Martin says:

    @ galechus

    In this shopping cart, the images can not be left out, because the script relies on them to identify the product.

    It could be possible to change it, but this would be the same as creating a brand new shopping cart.

    @ icy

    In the new tutorial about Making a Cool Login System, there is a special function I made, called send_mail() - it is defined in functions.php of the download files.

    You can use it instead of PHPMailer to easily send emails.

    You can see how it works from demo.php of the Login System. Copy the function from functions.php into your current shopping cart's order.php and you can use it.

  40. Pravin says:

    Fantabulous!

  41. charmane says:

    the total in the order.php don't seem to work. when i add two products, the last product's price will be the total..

  42. Sava says:

    Great tutorial and great idea. Love it

  43. Mia says:

    Martin- this is just so UBERKOOL ! This is def THEE best ajax/jquery cart I have seen - I had seen one which I thought was nicely built- but this ? This is like so Buck Rogers man, it def belongs in the future ! This totally ROX !
    Awesome :)

  44. paxton says:

    am having problems implementing the cart whenever i try to view the DOMO.PHP FILE I GET THIS ERROR.

    Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in /home/paxtons1/public_html/paxtonsdownloads.com/demo.php on line 57

    BUT THE CONNECTION TO MYSQL IS PERFECT

    COULD SOME ONE HELP PLEASE

  45. M.M.H.Masud says:

    good work and style of writing is really great. thanks

  46. Organzae says:

    I love your shopping cart. I hope one day I can do this tutorial but before I need to try Ajax. Any way. Thank you very much to share with us.

  47. toni says:

    Excellent tutorial, just stunning.

    I noticed that if the prices included cents, for example $199.80 for the iPod, $1199.50 for the iMac, etc., the TOTAL doesn't calculate the price correctly once I start removing the items. Does anyone know how to fix this?

  48. doe says:

    Wonderful tutorial. Is there a way to output order.php (the items in the cart) to a text file when the Checkout button is clicked?

  49. doe says:

    @ toni

    var 'totalrounded' should be added to the top of the script.js: var totalrounded = 0;

    Then: totalrounded = (Math.round(totalprice*100)/100).toFixed(2); could be used to fix the problem

  50. Gunaifi says:

    This is Great!!, but one thing...can i use pagination ? and what kind pagination script that u suggest ? any tutorial that i can read ?anyway thank u for sharing this great tutorial !!! :-)

  51. van71 says:

    Great product but i got no idea on how to set up the submit button to send email...

  52. toni says:

    @ van71

    I did it in 4 steps:

    1. Go to http://simplehtmldom.sourceforge.net/ and download PHP Simple HTML DOM Parser. The file is named simple_html_dom.php. Put it in your root folder (inside the demo folder)

    2. Add these two statements in order.php inside the php code at the top of the page, let's say on on line 2:

    include('simple_html_dom.php');
    ob_start();

    3. Wrap the php code at the middle of the page in order.php with . In other words add on line 51 and on line 85 (or 53 and 87 if you have added the two lines in step2)

    4. Add the following code in order.php after at the bottom of page and replace your@email.com with your email:

    find("#orderContent", 0);
    $ret = $e->plaintext;
    $fp = fopen("output.txt","w");
    fwrite($fp,$ret);
    fclose($fp);

    $file = file_get_contents('output.txt', FILE_USE_INCLUDE_PATH);

    $to = 'your@email.com';
    $subject = 'Order';
    $message = ''.$file.'';

    // To send HTML mail, the Content-type header must be set
    $headers = 'MIME-Version: 1.0' . "\r\n";
    $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

    mail($to, $subject, $message, $headers);

    ?>

    Now the order will be sent to your email and you should have output.html and output.txt inside your root folder (inside the demo folder), now that you might want to send output.txt to a remote server via ftp.

  53. Tj says:

    I am getting a this error when I click on the checkout button. Can anybody help me fix it?

    Parse error: parse error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting ',' or ';' in /Volumes/icemanRAID/www_root/sandbox/studentuse/tejasr/demo/order.php on line 78

  54. Taylor says:

    Toni: I ran into the same issue with formatting currency. I found a super simple solution. Ben Dewey has a FormatCurrency jquery plugin located at http://code.google.com/p/jquery-formatcurrency/

    So,
    1) in the head of the "demo" file make sure you include the jquery plugin
    2) crack open the script.js file. Go to line 152 and right below put this statement: $('#total').formatCurrency();
    Should be good to go after that. Here's what my update_total() looks like:

    function update_total()
    {
    if(totalprice)
    {

    $('#total').html('total: $'+totalprice);
    $('a.button').css('display','block');
    $('#total').formatCurrency();
    }
    else
    {
    $('#total').html('');
    $('a.button').hide();
    }
    }

  55. Taylor says:

    @Tj
    This May be a silly question, but is there a semicolon at the end of line 78 in your order.php file? That would be my prime suspect. Otherwise, did you happen to customize that line? Maybe there's an unclosed single quote?
    the original line is
    echo 'Total: $'.$total.'';

  56. qahar says:

    awesome.. wonderfull.... thanks to you :)

  57. Tj says:

    Thanks Taylor,

    I figured it out and fixed it yesterday. For some reason the stop after $total was missing. But i still get a notice saying that 'undefined variable total in' at the point where the mysql calls the result. I have disabled errors to temporarily fix that issue.

  58. toni says:

    @ van71

    Sorry, but part of the code from my post on November 13, 2009 is missing. I guess the server didn't like it and deleted it. Anyway I uploaded as a zip file order.php and simple_html_dom.php here:

    http://rapidshare.com/files/313973672/order_simplehtmldom.zip

    Just put them in your root folder (inside the demo folder), replace your@email.com with your email and your order will be sent to your email.

  59. kristin says:

    Very nice! It's a great starting point.

    Usability wise I would move the shopping cart to the left or right in a column and have it persist/scroll with the page so it's on the screen in larger resolutions. Hard to drag/drop to something that is below the fold.

  60. Moe says:

    it is amazing

    are there ability to integrate it with any of wp ecommerce plugin ?

  61. Vijay says:

    I want a jquery which should allow user to drag only one product at a time. Once user removes it then only he can drag other item. Please help me. I would be thankful to you, if you can suggest me with code.
    Thanks!

  62. El Verdugo says:

    Great tuto, i just wonder, how can i send, the things i buy, or "that ordered" to a database, for example the number of the product and the price, thanks!!!!!!!

  63. this is awesome, has anybody know the resources that explain about jquery single page or one page checkout process like www.fadedsoul.ca..?

    thanks a lot

  64. tz says:

    A drag and drop shopping cart is not a good idea. I worked at a company that did a LOT of usability testing on their shopping cart in every age bracket. Older users need things clearly defined and they have no idea what drag and drop even means. Regardless of how cool it is, this shopping cart would ultimately have to be scrapped for the good ole Add to Cart button that is the web standard.
    Several users even had no idea where to enter a credit card number even though it was clearly labeled in large text. Sorry, but people are dumb, and we as web developers have to dumb down our sites for them if we want to make money.

  65. Great. Any possibility for you to make a "part 2" integrating Paypal in it? ;)

  66. Blabbybeer says:

    This is a brillaint cart, I think drag and drop carts should become the new standard!

    I need some help though...

    My question is the same as Nikolius post from October 5, 2009 at 11:30 pm, (storing the cart contents from page to page) trouble is I don't know a great deal of javascript; could you give an example of how to implement the code you are talking about in your reply. Also instead of storing the data in a cookie could it be passed into a php session??

    Thanks in advance blabbybeer

  67. Dimitar Danailov says:

    $('.tooltip').hide(); // hiding the tooltip (sometimes it stays on screen after the drag)

    It's work ,but some times not hide the tooltip.

    Try in demo with Ipone and see the bug - not hide the tooltip.

    I try to fadeOut() ,but this time when bug is UP - fade tooltip 3 times.

    http://img200.imageshack.us/img200/8171/buggf.png

  68. I think it's the best one, I have ever seen about AJAX shopping cart.

  69. Matt says:

    Hey guys,

    I tried posting but nothing seemed to be approved. What I would like to do is this:

    I have created a new page called getRow.php which holds the call to pull the products from the DB as such:

    <?php

    $result = mysql_query("SELECT * FROM internet_shop");
    while($row=mysql_fetch_assoc($result))
    {
    echo '';
    }

    ?>

    What I would like to do it take that same logic but do it with JQuery like this:

    var grbData = $.ajax({
    type : "GET",
    url : "getRow.php",
    dataType: 'html',
    success: function (html) {
    $(".drag-desired").html(html);
    },
    error: function (xhr) {
    $('#errorDisplay').html('Error: '+ xhr.status +'' +xhr.statusText);
    }
    });

    The problem i'm seeing is the draggable and droppable effects no longer work.

    Please any insight as to why doing this would affect having the effects applied to the products images.

  70. jed says:

    this script is very nice.

    but after checkout how if i wants to connect with email from like after checkout user details form will appear like his name,email, address, mobile number and all this details with the products he purchased sent me to my email

    anybody can help me ?

    I'm waiting for replies

    jed

  71. Fernandos says:

    Absolutely Fantastic. You bring it to the point Martin!
    This is awesome as a tutorial, there are no questions left open.

    What I like about your Website is that you don't publish shit. You're writing really high quality tutorials! I highly appreciate that.
    Cheers and Beers mate! It's not quantity but quality that matters and your site is the evidence.

    And the best is that you offer a great user experience, because your Site design allows one to read an article without losing focus. All in one page, no dvisions into sections(which is bad practice imho).

    You mustn't give support here for free! Nettuts+ is taking money for their tutorials too. I can tell ya, I'd pay.

    Best regards
    Fernandos

  72. Bigboss says:

    @ Dimitar Danailov - I have the same issue!

    Does anyone know how to get rid of the multiple 'flashes' of the product when an image is clicked on and subsequently dragged around the screen or dropped into the shopping basket.

    I think it might be to do with the fact that the containment area is set to 'document' within script.js but not sure.

    Any ideas guys?

  73. Goran Mitev says:

    Amazing. Like it a lot. Keep up the good work tutorialzine.com

  74. raghu veer says:

    thank you for the nice shopping cart code, it will be really nice and helpful if you upgrade the script to work with jquery v1.4.2.

    I had tested this with jquery v1.3.2 and jqueryUI v1.8 and it worked nice :)

    may be, upgrading from simpletip to qtip is another good upgrade

    finally, storing the list of items in a cookie is a real good feature addition as buyer have choice to move between pages of the website while shopping.

    I understand this is a basic know-how to start with, incase, if you incorporate the above feature updates, it will be a quick start to many starters of jquery, thank you

    good work anyhow, all the best :)

    1. sebayang says:

      please change code after line :
      $row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img='".$img."'"));

      echo '{"status":1,"id":'.$row['id'].',"price":'.$row['price'].',"txt":
      "<table width=\"100%\" id=\"table_'.$row['id'].'\"><tr><td width=\"60%\">'.$row['name'].'</td><td width=\"10%\">$'.$row['price'].'</td><td width=\"15%\"><select name=\"'.$row['id'].'_cnt\" id=\"'.$row['id'].'_cnt\" onchange=\"change('.$row['id'].');\"><option value=\"1\">1</option><option value=\"2\">2</option><option value=\"3\">3</option><option value=\"4\">4</option><option value=\"5\">5</option><option value=\"6\">6</option></select></td><td width=\"15%\"><a href=\"#\" onclick=\"remove('.$row['id'].');return false;\" class=\"remove\">remove</a></td></tr></table>"
      }';

      my shopping cart, working on jquery-1.7.1.

  75. Meeza says:

    This tutorial is being used word for word on another site

    http://www.pixel2life.com/viewcomments/77527/ajax_based_shopping_cart_with_php_css_and_jquery/

  76. rathindraS says:

    Really NICE DEMO... THANKS A lot ......

    I totally appreciate

  77. great script !!!
    i encounterd an error : "Strict Standards: Only variables should be passed by reference in C:\Program Files (x86)\EasyPHP-5.3.2\www\shopping-cart-php-jquery\ajax\addtocart.php on line 9
    "

    could you help ?

  78. i made a mistake : it's on line 8 and not on line 9

  79. well, i found the solution : replace line 8 (for both tipp.php and addtocart.php) by:

    $img=mysql_real_escape_string(current(array_reverse(explode('/',$_POST['img']))));
    thx to http://www.geoffray.be/blog/php/only-variables-should-be-passed-by-reference

  80. andre says:

    thanks a lot, very good job.

    I try to use in IE6 and don't work, Are you know why?

    1. david says:

      are you use IE6? don't be silly and do update ! IE6 is over 10 years old ! start using new browsers !

  81. Lucille says:

    This is a really awesome tutorial! Great job to you Martin!

    Any easy way to integrate this into OsCommerce?

    I'm not sure if it would be possible to simply link the pages to the current store pages, or if we would need to hard-code it altogether?

    Also, I'm sure there's a way to offer this shopping cart solution as the first option and if the user doesn't have Javascript or whatever installed, then he'd be browsing the site with the second option. There would be more involved, obviously, but I'm almost certain it can be done.

    Any help and advice is greatly appreciated.

    Thanks.

  82. Seul says:

    Hi,

    have a question how would it be possible to make it more dynamic.

    I tried to do some paging and selection following some form items, however after load i fail to get the "ajax" working, and items are no more "dragable".

    Is there a simple way to do this?

    Regards,
    s

  83. Adesina Omoniyi Mark says:

    Nice tutorial. i have learnt a lot here. Keep them coming.

  84. Lau says:

    Excuse me Martin, may i know how to make a scroll bar in the product part, and the product how to show for 4 items in a row

  85. suresh says:

    Nice tutorial..Thanks

  86. sebayang says:

    Great tutorial, working on jquery-1.3.2 but not working on jquery-1.7.1.
    when im drag the product, icon loading on chart busy. anybody can help me

  87. Tulio Gomez says:

    good, updated versions and everything works fine now .....
    I put the links that use

    http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"
    http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"

    1. sebayang says:

      May I got, updated links. thx.

  88. Juan says:

    Hello. Thanks for this nice piece of code. It is exactly what I was looking for. But... well, I've tried ALL kind of tricks and I can't run your excellent script in IE, including of course IE9. I thought that the problem was mine -in my localhost- but I tried with your own online demo and the result is the same: the products icons remains in the products area (freezed), the "loading.gif" icon keeps its rotation forever in the webpage and it never disappear. Any suggestion, please?

    1. yy says:

      Hi Martin, thx for this great tutorial^^...but i met the same prob same wif Juan......

      May i know wat's the prob?

  89. Neil says:

    Hi,

    nice tutorial for the beginner that I am. Like sebayang before when I drag a product into the cart the loading/busy icon appears but it stalls at that. Can anyone point out what code I need to change (in very simple terms for a complete novice!!).

    Many thanks!!

    If it helps this is what I have in my demo.php file

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>

    <script type="text/javascript" src="simpletip/jquery.simpletip-1.3.1.pack.js"></script>

    <script type="text/javascript" src="script.js"></script>

    1. PvT says:

      Hi Neil,
      The file 'addtocart.php' (subfolder 'Ajax') contains the statement:
      $img=mysql_real_escape_string(end(explode('/',$_POST['img']));

      You will have to change that into:
      $post = explode('/',$_POST['img']);
      $img=mysql_real_escape_string(end($post));

  90. Ben says:

    Hello Martin,

    can you help me,

    I would like to get the information quantity from the on change method? Because I will save the datas in database, because the card ist empty if i refresh the site.

    I have problems to change the code correctly.

    Thank you very much for your help.

    Ben

  91. antonova says:

    in Opera browser, which is my default, dragging is not working, Is there a solution?
    thanks in advance Martin!

  92. Jasa says:

    Hi Martin, great tutorial... do you have any idea how to approach customizing this cart to work on a jquery mobile/ phonegap framework? Any tips would be much appreciated, thanks in advance=) Jasa

  93. Terry says:

    Hi, any idea why the remove function is not working in Chrome v32.0.1700.107 and Firefox v27.0.1? It works fine in IE11, but in the others, the red "remove" text disappears but the table row stays.

    Due to the "loading" hanging error noted in posts above, I can't check it against your online demo to see if it works here.

  94. Terry says:

    Hi,

    Just a tip for anyone trying to use this code. If you are using Chrome version 24 or up and FF 27, you will need to rename the remove() function in script.js, as these new browsers have a built in DOM feature named remove. Without renaming the function you will not be able to delete items from the cart. I just renamed the function itself and the call to it in 'addtocart.php'

    Aside from that, this is a great tutorial for anyone wanting to learn this sort of thing.

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links