• Home
  • New Entries
  • Popular Entries
  • Submit a Story
  • About

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

01.CREATE TABLE IF NOT EXISTS `internet_shop` (
02.  `id` int(6) NOT NULL auto_increment,
03.  `img` varchar(32) collate utf8_unicode_ci NOT NULL default ,
04.  `name` varchar(64) collate utf8_unicode_ci NOT NULL default ,
05.  `description` text collate utf8_unicode_ci NOT NULL,
06.  `price` double NOT NULL default ,
07.  PRIMARY KEY  (`id`),
08.  UNIQUE KEY `img` (`img`)
09.) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ;
10.
11.INSERT INTO `internet_shop` VALUES(1, iPod.png, iPod, The original and popular iPod., 200);
12.INSERT INTO `internet_shop` VALUES(2, iMac.png, iMac, The iMac computer., 1200);
13.INSERT INTO `internet_shop` VALUES(3, iPhone.png, iPhone, This is the new iPhone., 400);
14.INSERT INTO `internet_shop` VALUES(4, iPod-Shuffle.png, iPod Shuffle, The new iPod shuffle., 49);
15.INSERT INTO `internet_shop` VALUES(5, iPod-Nano.png, iPod Nano, The new iPod Nano., 99);
16.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

01.<div id="main-container"> <!-- the main container element -->
02.
03.<div class="tutorialzine">    <!-- some headings -->
04.<h1>Shopping cart</h1>
05.<h3>The best products at the best prices</h3>
06.</div>
07.
08.<div class="container">   <!-- the first section - products -->
09.
10.<span class="top-label">
11.<span class="label-txt">Products</span> <!-- section label -->
12.</span>
13.
14.<div class="content-area">
15.<div class="content drag-desired">    <!-- assigning a common content class and an individually targeted drag-desired class -->
16.
17.<?php
18.// php code that generates the products
19.?>
20.
21.<div class="clear"></div>   <!-- clearing the floats -->
22.</div>
23.</div>
24.
25.<div class="bottom-container-border"> <!-- bottom part of the section -->
26.</div>
27.
28.</div>    <!-- closing the products section -->
29.
30.<div class="container">   <!-- the second section - shopping cart -->
31.
32.<span class="top-label">
33.<span class="label-txt">Shopping Cart</span>    <!-- label for the section -->
34.</span>
35.
36.<div class="content-area">
37.<div class="content drop-here">   <!-- content class, shared with the product section above, and the targeted drop-here class -->
38.<div id="cart-icon">
39.<img src="img/Shoppingcart_128x128.png" alt="shopping cart" class="pngfix" width="128" height="128" />    <!-- using the pngfix class -->
40.<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 -->
41.</div>
42.
43.<form name="checkoutForm" method="post" action="order.php">   <!-- the form -->
44.<div id="item-list">  <!-- in this div we insert all the products in the shopping cart -->
45.
46.</div>
47.</form>   <!-- closing the form -->
48.
49.<div class="clear"></div>   <!-- clearing -->
50.
51.<div id="total"></div>  <!-- the total price goes here -->
52.<div class="clear"></div>   <!-- clearing the floats -->
53.
54.<a href="" onclick="document.forms.checkoutForm.submit(); return false;" class="button">Checkout</a>    <!-- the submit button, hidden by default, notice the onclick attribute -->
55.
56.</div>
57.</div>
58.
59.<div class="bottom-container-border"> <!-- bottom part of the section -->
60.</div>
61.
62.</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 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
view sourceprint?
001.body,h1,h2,h3,p,td,quote,small,form,input,ul,li,ol,label{
002./* resetting some of the styles for browser compatibility */
003.    margin:0px;
004.    padding:0px;
005.    font-family:Arial, Helvetica, sans-serif;
006.}
007.
008.body{
009.    color:#555555;
010.    font-size:13px;
011.    background-color:#282828;
012.}
013.
014..clear{ /* implementing the clear-fix hack for fixing floated layouts */
015.    clear:both;
016.}
017.
018.#main-container{    /* this is the main container, holding the two sections */
019.    width:700px;
020.    margin:20px auto;
021.}
022.
023..container{ /* the main container of our content sections - the products and the shopping cart */
024.    margin-bottom:40px;
025.}
026.
027..top-label{ /* the outer span comprising the label */
028.    background:url(img/label_bg.png) no-repeat; /* showing the left part of label_bg.png - a wide round-cornered image */
029.    display:inline-block;
030.    margin-left:20px;
031.    position:relative;
032.    margin-bottom:-15px;    /* the whole label is lowered on the product section */
033.}
034.
035..label-txt{ /* the inner span - red border in the illustration above */
036.    background:url(img/label_bg.png) no-repeat top right;   /* shows the right part of the wider label_bg.png */
037.    display:inline-block;
038.    font-size:10px;
039.    height:36px;
040.    margin-left:10px;   /* leaves space on the left, so that the outer span can show its background */
041.    padding:12px 15px 0 5px;
042.    text-transform:uppercase;
043.}
044.
045..content-area{  /* The top part of the rounded container image, see the illustration above */
046.    background:url(img/container_top.png) no-repeat #fcfcfc;
047.    padding:15px 20px 0 20px;
048.}
049.
050..content{   /* shared by the two sections */
051.    padding:10px;
052.}
053.
054..drag-desired{  /* individually targeted properties */
055.    background:url(img/drag_desired_label.png) no-repeat top right;
056.    padding:30px;
057.}
058.
059..drop-here{ /* not shared with the other sections */
060.    background:url(img/drop_here_label.png) no-repeat top right;
061.}
062.
063..bottom-container-border{   /* the bottom rounded graphic, that completes the section */
064.    background:url(img/container_bottom.png) no-repeat;
065.    height:14px;
066.}
067.
068..product{   /* styling the products */
069.    border:2px solid #F5F5F5;
070.    float:left;
071.    margin:15px;
072.    padding:10px;
073.}
074.
075..product img{
076.    cursor:move;
077.}
078.
079.p.descr{
080.    padding:5px 0;
081.}
082.
083.small{
084.    display:block;
085.    margin-top:4px;
086.}
087.
088..tooltip{   /* the tooltips, this div is created by the simpletip plugin */
089.    position: absolute;
090.    top: 0;
091.    left: 0;
092.    z-index: 3;
093.    display: none;
094.
095.    background-color:#666666;
096.    border:1px solid #666666;
097.    color:#fcfcfc;
098.
099.    padding:10px;
100.
101.    -moz-border-radius:12px;    /* rounded corners */
102.    -khtml-border-radius: 12px;
103.    -webkit-border-radius: 12px;
104.    border-radius:12px;
105.}

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.

001.#cart-icon{ /* the div that contains the shopping cart icon */
002.    width:128px;
003.    float:left;
004.    position:relative;  /* changing the position to relative so that ajax-loader is positioned relative to it */
005.}
006.
007.#ajax-loader{
008.    position:absolute;  /* absolute positioning makes an element relative to its parent if the latter has positioning different from the default  */
009.    top:0px;
010.    left:0px;
011.    visibility:hidden;
012.}
013.
014.#item-list{ /* the contents of the shopping cart goes into this div */
015.    float:left;
016.    width:490px;
017.    margin-left:20px;
018.    padding-top:15px;
019.}
020.
021.a.remove,a.remove:visited{  /* the REMOVE link */
022.    color:red;
023.    font-size:10px;
024.    text-transform:uppercase;
025.}
026.
027.#total{ /* the total cost div */
028.    clear:both;
029.    float:right;
030.    font-size:10px;
031.    font-weight:bold;
032.    padding:10px 12px;
033.    text-transform:uppercase;
034.}
035.
036.#item-list table{   /* every product in the shopping cart is positioned inside the item-list div */
037.    background-color:#F7F7F7;
038.    border:1px solid #EFEFEF;
039.    margin-top:5px;
040.    padding:4px;
041.}
042.
043.a.button,a.button:visited{  /* the CHECKOUT button */
044.    display:none;
045.
046.    height:29px;
047.    width:136px;
048.
049.    padding-top:15px;
050.    margin:0 auto;
051.    overflow:hidden;
052.
053.    color:white;
054.    font-size:12px;
055.    font-weight:bold;
056.    text-align:center;
057.    text-transform:uppercase;
058.
059.    background:url(img/button.png) no-repeat center top;    /* showing only the top part of the background image */
060.}
061.
062.a.button:hover{
063.    background-position:bottom; /* on hover we show the bottom part of the image */
064.    text-decoration:none;
065.}
066.
067./* Some less interesting classes */
068.
069.a, a:visited {
070.    color:#00BBFF;
071.    text-decoration:none;
072.    outline:none;
073.}
074.
075.a:hover{
076.    text-decoration:underline;
077.}
078.
079.h1{
080.    font-size:28px;
081.    font-weight:bold;
082.    font-family:"Trebuchet MS",Arial, Helvetica, sans-serif;
083.}
084.
085.h2{
086.    font-weight:normal;
087.    font-size:20px;
088.
089.    color:#666666;
090.    text-indent:30px;
091.    margin:20px 0;
092.}
093.
094..tutorialzine h1{
095.    color:white;
096.    margin-bottom:10px;
097.    font-size:48px;
098.}
099.
100..tutorialzine h3{
101.    color:#F5F5F5;
102.    font-size:10px;
103.    font-weight:bold;
104.    margin-bottom:30px;
105.    text-transform:uppercase;
106.}
107.
108..tutorial-info{
109.    color:white;
110.    text-align:center;
111.    padding:10px;
112.    margin-top:-20px;
113.}

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
view sourceprint?
1.<!--[if lt IE 7]>
2.<style type="text/css">
3.    .pngfix { behavior: url(pngfix/iepngfix.htc);}  /* this is a special htc file that fixes the IE6 transparency issues */
4.    .tooltip{width:200px;}; /* provide a default width for the tooltips */
5.</style>
6.<![endif]-->

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

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

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

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

01.define(INCLUDE_CHECK,1);
02.require "../connect.php";
03.
04.if(!$_POST[img]) die("There is no such product!");
05.
06.$img=mysql_real_escape_string(end(explode(/,$_POST[img])));
07.
08.$row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img=".$img.""));
09.
10.if(!$row) die("There is no such product!");
11.
12.echo <strong>.$row[ ame].</strong>
13.<p class="descr">.$row[ wouldescription].</p>
14.<strong>price: $.$row[price].</strong>
15.<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

01.define(INCLUDE_CHECK,1);
02.require "../connect.php";
03.
04.if(!$_POST[img]) die("There is no such product!");
05.
06.$img=mysql_real_escape_string(end(explode(/,$_POST[img])));
07.$row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img=".$img.""));
08.
09.echo {status:1,id:.$row[id].,price:.$row[price].,txt:
10.
11.<table width="100%" id="table_.$row[id].">
12.<tr>
13.<td width="60%">.$row[ ame].</td>
14.<td width="10%">$.$row[price].</td>
15.<td width="15%"><select name=".$row[id].\_cnt" id=".$row[id].\_cnt" onchange="change(.$row[id].);">
16.<option value="1">1</option>
17.<option value="2">2</option>
18.<option value="3">3</option></slect>
19.
20.</td>
21.<td width="15%"><a href="#" onclick="remove(.$row[id].);return false;" class="remove">remove</a></td>
22.</tr>
23.</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

01.<?php
02.
03.define(INCLUDE_CHECK,1);
04.require "connect.php";
05.
06.if(!$_POST) // if there is no data submitted to the form
07.{
08.    if($_SERVER[HTTP_REFERER])    // redirect
09.    header(Location : .$_SERVER[HTTP_REFERER]);
10.    exit;   // and exit
11.}
12.
13.?>
14.
15.<!-- XHTML code.. -->
16.
17.<?php
18.
19.$cnt = array();
20.$products = array();
21.
22.foreach($_POST as $key=>$value)
23.{
24.    $key=(int)str_replace(\_cnt,,$key);
25.    $products[]=$key;   // store the product ids in an array
26.    $cnt[$key]=$value;  // create a key / value pair where for each product id there is a corresponding value being the number of products
27. purchased}
28.
29.$result = mysql_query("SELECT * FROM internet_shop WHERE id IN(".join($products,,).")");  // selecting all the products with the IN() function
30.
31.if(!mysql_num_rows($result))    // no products found
32.{
33.    echo <h1>There was an error with your order!</h1>;
34.}
35.else
36.{
37.    echo <h1>You ordered:</h1>;
38.    while($row=mysql_fetch_assoc($result))
39.    {
40.        echo <h2>.$cnt[$row[id]]. x .$row[ ame].</h2>;
41.        $total+=$cnt[$row[id]]*$row[price];
42.    }
43.
44.    echo <h1>Total: $.$total.</h1>;
45.}
46.
47.?>

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

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.
view sourceprint?
1.<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
2.<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
3.<script type="text/javascript" src="simpletip/jquery.simpletip-1.3.1.pack.js"></script> <!-- the jQuery simpletip plugin -->
4.<script type="text/javascript" src="script.js"></script> <!-- our script.js file -->

Now we can continue with our script.


script.js

01.var purchased=new Array();  //an array containing all the products we have purchased so far
02.var totalprice=0;   //the total price
03.
04.$(document).ready(function(){
05.
06.    $(.product).simpletip({   //using the simpletip plugin
07.
08.        offset:[40,0],
09.        content:<img style="margin:10px;" src="img/ajax_load.gif" alt="loading" />, // default content
10.        onShow: function(){
11.
12.            var param = this.getParent().find(img).attr( isrc);
13.            // fix for IE6
14.            if($.browser.msie && $.browser.version==6.0)
15.            {
16.                param = this.getParent().find(img).attr( istyle).match(/src="([^"]+)"/);
17.                param = param[1];
18.            }
19.
20.            // after the tooltip is shown, load the tips.php file and pass the image name as a parameter
21.            this.load(ajax/tips.php,{img:param});
22.        }
23.
24.    });
25.
26.    $(".product img").draggable({   // enable all product images to be dragged
27.
28.    containment: wouldocument,
29.    opacity: 0.6,
30.    revert: invalid,
31.    helper: clone,
32.    zIndex: 100
33.
34.    });
35.
36.    $("div.content.drop-here").droppable({  // convert the shopping cart to a droppable
37.
38.            drop:
39.                function(e, ui)
40.                {
41.                    var param = $(ui.draggable).attr( isrc);
42.                    // IE6 fix
43.                    if($.browser.msie && $.browser.version==6.0)
44.                    {
45.                        param = $(ui.draggable).attr( istyle).match(/src="([^"]+)"/);
46.                        param = param[1];
47.                    }
48.
49.                    addlist(param); // the special addlist function - see below
50.                }
51.
52.    });
53.
54.});

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.

001.function addlist(param)
002.{
003.    // the addlist function ads a product to the shopping cart
004.
005.    $.ajax({    // sending an ajax request to addtocart.php
006.    type: "POST",
007.    url: "ajax/addtocart.php",
008.    data: img=+encodeURIComponent(param), // the product image as a parameter
009.    dataType: json,   // expecting json
010.    beforeSend: function(x){$(#ajax-loader).css(visibility,visible);},    // showing the loading gif
011.    success: function(msg){
012.
013.        $(#ajax-loader).css(visibility,hidden);   // hiding the loading gif animation
014.        if(parseInt(msg.status)!=1)
015.        {
016.            return false;   // if there has been an error, return false
017.        }
018.        else
019.        {
020.            var check=false;
021.            var cnt = false;
022.
023.            for(var i=0; i<purchased.length;i++)
024.            {
025.                if(purchased[i].id==msg.id) // find if we have already bought this prduct
026.                {
027.                    check=true;
028.                    cnt=purchased[i].cnt;
029.
030.                    break;
031.                }
032.            }
033.
034.            if(!cnt)    // if we haven bought it yet, or we have removed it from the purchases, we insert it in the shopping cart
035.                $(#item-list).append(msg.txt);
036.
037.            if(!check)  // if we haven bought it yet, insert it in the purchased array
038.            {
039.                purchased.push({id:msg.id,cnt:1,price:msg.price});
040.            }
041.
042.            else    // else if we have bought it
043.            {
044.                if(cnt>=3) return false; // 3 products of type max
045.
046.                purchased[i].cnt++;
047.                $(#+msg.id+\_cnt).val(purchased[i].cnt); // update the select box
048.            }
049.
050.            totalprice+=msg.price;  // recalculate the price
051.            update_total(); // update the total div
052.
053.        }
054.
055.        $(.tooltip).hide();   // hiding the tooltip (sometimes it stays on screen after the drag)
056.
057.    }
058.    });
059.}
060.
061.function findpos(id)    // a helper function that finds the position at which the product is inserted in the array, returns the position
062.{
063.    for(var i=0; i<purchased.length;i++)
064.    {
065.        if(purchased[i].id==id)
066.            return i;
067.    }
068.
069.    return false;
070.}
071.
072.function remove(id) // remove a product from the shopping cart
073.{
074.    var i=findpos(id);  // find its position in the array
075.
076.    totalprice-=purchased[i].price*purchased[i].cnt;    // recalculate the price
077.    purchased[i].cnt = 0;   // reset the counter
078.
079.    $(#table_+id).remove();   // remove it from the cart
080.    update_total(); // update the total price counter on the page
081.}
082.
083.function change(id) // evoked when we change the number of products via the select area
084.{
085.    var i=findpos(id);
086.
087.    totalprice+=(parseInt($(#+id+\_cnt).val())-purchased[i].cnt)*purchased[i].price;
088.
089.    purchased[i].cnt=parseInt($(#+id+\_cnt).val());
090.    update_total();
091.}
092.
093.function update_total() // function that updates the total price div on the page
094.{
095.    if(totalprice)
096.    {
097.        $(#total).html( otal: $+totalprice);    // if we have bought somehitng, show the total price div and the purchase button
098.        $(a.button).css( wouldisplay,lock);
099.    }
100.    else    // hide them
101.    {
102.        $(#total).html();
103.        $(a.button).hide();
104.    }
105.}

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.

 Original Source:
http://tutorialzine.com/2009/09/shopping-cart-php-jquery/

AddThis Social Bookmark Button

Posted at 10:44:31 am | Permalink | Posted in CSS  jQuery  

Related Stuff

  • MooV: Using cutting edge Video phones and Software Video Phones - coupling all that with VoIP and empowering the disabled.

  • Moo Telecom: VoIP communications made easy - Ring anyway with the fun and ease of using a normal phone

  • TagR:Mobile Social Network with Real Time Locations Based services, and Ambience Intelligence, VoiP, IM, Skype, Googletalk, Mapping, Flickr, Events, Calendaring, Scheduling, SecondLife Support

  • ClearSMS : ClearSMS is a Web-based application that lets you send bulk SMS messages to your customers, contacts, or just about anyone.

  • Jajah:jah is a VoIP (Voice over IP) provider, founded by Austrians Roman Scharf and Daniel Mattes in 2005[1]. The Jajah headquarters are located in Mountain View, CA, USA, and Luxembourg. Jajah maintains a development centre in Israel.

  • Skype: It’s free to download and free to call other people on Skype. Skype the number one voice over ip software

  • PrivatePhone: a free local phone number with voicemail and messages you can check online or from any phone.

Top Stuff

MessengerFX

e-messenger

ILoveIM

Top 20 Ruby CMS

MSN Web Messenger

eBuddy



About Ajaxlines

Ajaxlines is a project focused on providing its audience with a database of most of Ajax related articles, resources, tutorials and services from around the world.

Its purpose is to showcase the power of Ajax and to act as a portal to the Ajax development community.


Search


Topics

  • .Net (171)
  • Ajax (89)
  • Ajax Games (10)
  • Articles (95)
  • Bookmarking (35)
  • Calendar (21)
  • Chat (45)
  • ColdFusion (3)
  • CSS (79)
  • Email (23)
  • Facebook (84)
  • Flash (19)
  • Google (54)
  • Html (28)
  • Image (11)
  • International Calls & VOIP (7)
  • Java (56)
  • Javascript (271)
  • jQuery (171)
  • JSON (70)
  • Perl (2)
  • PHP (162)
  • Presentation (19)
  • Python (3)
  • Resources (2)
  • RSS (8)
  • Ruby (31)
  • Storage (4)
  • Toolkits (103)
  • Tutorials (224)
  • UI (11)
  • Utilities (174)
  • Web2.0 (18)
  • XmlHttpRequest (28)
  • YUI (13)

© 2006 www.ajaxlines.com. All Rights Reserved. Powered by IRange