An AJAX Based Shopping Cart with PHP, CSS & jQuery

Download

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.

Note: This tutorial is quite old and doesn't work in PHP7 and above. We are keeping it online only as a reference.

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.

i12.png
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.

i2.png
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.

i3.png
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.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

Max Stanworth

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

Cheer Up.. That's really gr8

paul rostorp

Awesome!!! thanks,

Niiiice article! Thank you for sharing!

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

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...

This is pretty sweet, thanks for the tutorial.

Nice in depth tut. Good work!

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

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.

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.

Martin Angelov

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.

Hey there,

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

WebDevHobo

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.

Cool shopping cart tutorial!

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

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

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,

As good looking as simple really nice tut

very nice! thank you

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 ;)

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?

Martin Angelov

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.

how nice.
thank you

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)

Nano Thailand

Good job.

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

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

Martin Angelov

@ 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.

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!;)

janus lee

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

janus lee

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

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

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 &amp;&amp; $.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?

Martin Angelov

@ 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.

thx, but how do this on link not img.

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

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

Martin Angelov

@ 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.

Fantabulous!

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..

Great tutorial and great idea. Love it

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 :)

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

M.M.H.Masud

good work and style of writing is really great. thanks

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.

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?

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?

@ 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

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 !!! :-)

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

@ 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();

  1. 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)

  2. Add the following code in order.php after at the bottom of page and replace [email protected] 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 = '[email protected]';
$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.

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

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();
}

}

@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.'';

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

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.

@ 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 [email protected] with your email and your order will be sent to your email.

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.

it is amazing

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

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!

El Verdugo

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!!!!!!!

drian nugroho

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

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.

Olivier Turbis

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

Blabbybeer

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

Dimitar Danailov

$('.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

Zamshed Farhan

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

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(&quot;SELECT * FROM internet_shop&quot;);
            while($row=mysql_fetch_assoc($result))
            {
                echo &#039;';
            }

            ?&gt;

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.

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

Fernandos

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

@ 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?

Goran Mitev

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

raghu veer

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 :)

sebayang

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.

rathindraS

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

I totally appreciate

agence internet

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 ?

agence internet

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

agence internet

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

thanks a lot, very good job.

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

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

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.

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

Adesina Omoniyi Mark

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

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

Nice tutorial..Thanks

sebayang

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

Tulio Gomez
sebayang

May I got, updated links. thx.

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?

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

May i know wat's the prob?

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&gt;
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script&gt;

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

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

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));

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

antonova

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

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

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.

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.

jan jaime

hi guys you did amazing job, do you have a pdo php like this version because your using the older version of php? is it possible that i can use pdo like this. If you have source code can you share thanks Godbless