Building an E-Commerce Shop Front

The shopping basket

The MusicMad shopping basket relies exclusively on cookies, in particular the basket cookie which we set. Given we have server-side programming available to us you may wonder why we still use cookies stored on the client machine for storing our basket's contents instead of say, session variables or the database.

The main reason is scalability. Storing any data on the server consumes the finite server resources available. On a popular web site at peak times user sessions could run into hundreds of thousands, maybe more. Session variables consume resources until the user's session times out, which is 20 minutes by default. Using a database to store basket contents is a possibility but again your database could grow very large, even if just temporarily. It also requires database connection each time a user accesses their basket which, again, is costly in terms of server memory and processing time. It's likely the user's machine has more than sufficient resources to cope with our shopping basket's storage and processing, so it makes sense to distribute responsibility here.

Adding Items to the Basket

When we wrote the code which dynamically creates a page with a list of products, we also put an <A> tag for each item with Add to Basket as the link's text and AddToBasket.asp as its href property. We also appended ItemId, the number of CDs wanted (by default 1), ArtistName, record Title and Price per item to the end of the <A> tag's href. We can now retrieve those values in our server-side ASP script.

The values passed in the URL were also escaped into a URL-encoded form. Effectively, this means that non-alphabetic characters were converted to a hexadecimal format. For example, a space would become %20 if there were any in the link. So, the first thing we must do is unescape those values and split them up into the individual data values for ItemId, ArtistName etc. We use the ItemId to check there is not already one of those items already in the basket. If there is then we get the current quantity in the basket and add one to it. Finally, we use the setItemCookie function that's been made available by including our server-side global module at the top of the page. It's perhaps worth mentioning here that server-side include directives cannot have include directives in them to other files, precluding the errors inherent in an 'include chain'. This is managed as ASP has a one-step preprocessing stage by any server-side code is executed and the include statement is dealt with in this stage.

<!--#include file="ServerSideGlobalDef.inc"-->
<%  
   // decode query string from HTTP form
   var sQueryString =  unescape(Request.QueryString);
   var sBasketCookie = new String(Request.Cookies("Basket"));
 
   // String is in form
   // IDItemId&Qty&ArtistName&Description&Price
   var NewItemData = sQueryString.split("&");
 
   if (sBasketCookie.indexOf(NewItemData[0] + "&") >= 0 )
   {
     var ExistItemData = getItemFromCookie(NewItemData[0],sBasketCookie);
     NewItemData[1] =parseInt(NewItemData[1])+parseInt(ExistItemData[1]);
   }
  
   Response.Cookies("Basket")=setItemToCookie(NewItemData,sBasketCookie);
%>

We complete the page by adding a message informing the user what has just been successfully added to their basket.

It's also nice, from a user interface point of view, to give them the option to view their basket or proceed to the checkout by putting a form with two buttons on the page. The onClick event handler code has been added to the HTML tags and simply replaces the current page of the main frame with the relevant pages for viewing the basket, which we create next, and the checkout page which will be created later.

<HTML>
<BODY>
<BR><BR><BR>
<P align="center">
   <FONT FACE="Comic Sans MS" SIZE="3">
      1 copy of <STRONG><%= NewItemData[3] %></STRONG><BR>
      by <STRONG><%= NewItemData[2] %></STRONG> 
      has been added to your shopping basket
   </FONT>
</P>
 
<DIV align="center">
<FORM ACTION="" method="POST">
   <INPUT TYPE="Button" NAME="cmdCheckout" VALUE="Proceed to Checkout" _
          onClick="window.location.replace('checkout_frame.htm')">
   <INPUT TYPE="Button" NAME="cmdBasket" VALUE="View Basket"  _
          onClick="window.location.replace('viewbasket.asp')">
</FORM>
</DIV>
</BODY>
</HTML>

Save the page as AddToBasket.asp

Viewing the Basket's Contents

The screenshot above shows what we are aiming for as regards the contents and layout of the basket. As well as showing each item, the quantity, price and total price we also have a summary of the order cost at the end.

Before we create the page that views the basket, we are going to create another server-side include file: Basket.inc. As you will see later, viewing the contents of the basket is something we need to do in a number of different places on the site, so by creating an include file we keep the code in one place making debugging and maintenance easier.

The basket include file retrieves each item from the basket cookie used to store the goods and produces a table listing the item's artist, description, quantity selected, price per item and cost of the total quantity of that item in the basket. Finally at the end of the table it produces a sub total of the cost of all the items, cost of delivery and final cost.

The include file uses a variable bReadOnly which we define and set outside the include file. If bReadOnly is false then in each item row in the table, the quantity of each item is displayed inside a text box. Below the table is a button which when clicked updates the quantities based on the values in the quantity boxes. If the user wishes to remove an item from the basket they enter 0 in its quantity text box and hit the Update Quantities button.

If bReadOnly has been set to true then quantities are displayed as plain text and there is no Update Quantities button. This gives us a method of displaying a non-updateable summary of basket items at checkout.

Our first task is to make sure the user is viewing the very latest details and not a stale cached version of the basket. We can accomplish this by setting the Response.Expires property to -1, as we did in browse.asp, to ensure the page expires as soon as it is loaded by the browser.

Following that is a JavaScript form validation function, checkQtys. This function loops through each element in the basket's form and if the element is a text box, (i.e. its type property is text) we check that the contents are a valid whole number. It's worth mentioning here that the <FORM> tag is actually written outside the include file as this makes it easier to set parameters such as the form's action, method, name and events. This makes our whole code a little more adaptable to different situations. The validation routine does not need to know the name of the form it's validating because we pass the form object itself as the function's parameter.

If parsing the text box's value to an integer produces NaN, we know that the user has entered some invalid value. We react to this with a warning message, then set focus to the offending element and select the text inside it (just to make things really clear to the user). Also, false is returned from the function and is important if this routine is used as the onSubmit event handler, as returning false cancels the submit event.

<% Response.Expires = -1; %>
<SCRIPT LANGUAGE="JavaScript">
function checkQtys(theForm)
{
   for (var iElement = 0; iElement < theForm.length;iElement++)
   {
      if (theForm[iElement].TYPE == "text")
      {
         if (isNaN(parseInt(theForm[iElement].VALUE)) || _
               (parseInt(theForm[iElement].VALUE) < 0))
         {
            alert("The quantity you have entered is invalid\n _
                   Only whole numbers are valid in this box");
            theForm[iElement].focus();
            theForm[iElement].select();
            return false;
         }
      }
   }
   return true;
}
</SCRIPT>

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Better train people and risk they leave – than do nothing and risk they stay.” - Anonymous