Building an E-Commerce Shop Front

The ordering system (2)

The cmdPrevious button at the end of the form contains history.back() in its onClick event rather than specifying the page with window.location.href='personaldetails.asp'. If the history object's back() method is used then the personal details page is displayed with all the information that the user filled in. Using location.href however returns you to a blank form to fill out once again.

   <DIV align="center">
   <TABLE>
   <TR>
      <TD COLSPAN=4>
         <STRONG>
            <FONT FACE="Comic Sans MS" SIZE="2">Card Holders Name</FONT>
         </STRONG>
      </TD>
   </TR>
   <TR>
      <TD COLSPAN="4">
         <INPUT TYPE="TEXT" NAME="txtCardHolderName" maxlength="50">
      </TD>
   </TR>
   <TR>
      <TD COLSPAN=4>
         <BR>
         <STRONG>
            <FONT FACE="Comic Sans MS" SIZE="2">Credit Card No.</FONT>
         </STRONG>
      </TD>
   </TR>
   <TR>
      <TD COLSPAN="4">
         <INPUT TYPE="TEXT" NAME="txtCardNo" maxlength=20>
      </TD>
   </TR>
   <TR>
      <TD COLSPAN=4>
      <BR>
         <STRONG>
            <FONT FACE="Comic Sans MS" SIZE="2">Credit Card Type</FONT>
         </STRONG>
      </TD>
   </TR>
   <TR>
      <TD>
         <FONT FACE="Comic Sans MS" SIZE="2">Visa</FONT> 
         <INPUT NAME="radCardType" TYPE="radio" VALUE="Visa">
      </TD>
      <TD>
         <FONT FACE="Comic Sans MS" SIZE="2">Mastercard</FONT>
         <INPUT NAME="radCardType" TYPE="radio" VALUE="Mastercard">
      </TD>
      <TD>
         <FONT FACE="Comic Sans MS" SIZE="2">Switch</FONT>
         <INPUT NAME="radCardType" TYPE="radio" VALUE="Switch">
      </TD>
      <TD>
         <FONT FACE="Comic Sans MS" SIZE="2">Access</FONT>
         <INPUT NAME="radCardType" TYPE="radio" VALUE="Access">
      </TD>
   </TR>
   <TR>
      <TD COLSPAN="4">
      <BR>
         <STRONG>
            <FONT FACE="Comic Sans MS" SIZE="2">Card Expiry Date</FONT>
         </STRONG>
      </TD>
   </TR>
   <TR>
      <TD COLSPAN="4">
         <FONT FACE="Comic Sans MS" SIZE="2">
         <SELECT NAME="cboExpMonth" SIZE="1">
            <OPTION VALUE="01">01</OPTION>
            <OPTION VALUE="02">02</OPTION>
            <OPTION VALUE="03">03</OPTION>
            <OPTION VALUE="04">04</OPTION>
            <OPTION VALUE="05">05</OPTION>
            <OPTION VALUE="06">06</OPTION>
            <OPTION VALUE="07">07</OPTION>
            <OPTION VALUE="08">08</OPTION>
            <OPTION VALUE="09">09</OPTION>
            <OPTION VALUE="10">10</OPTION>
            <OPTION VALUE="11">11</OPTION>
            <OPTION VALUE="12">12</OPTION>
         </SELECT>
         <SELECT NAME="cboExpYear" SIZE="1">
            <OPTION VALUE="1999">1999</OPTION>
            <OPTION VALUE="2000">2000</OPTION>
            <OPTION VALUE="2001">2001</OPTION>
            <OPTION VALUE="2002">2002</OPTION>
            <OPTION VALUE="2003">2003</OPTION>
            <OPTION VALUE="2004">2003</OPTION>
            <OPTION VALUE="2005">2003</OPTION>
         </SELECT>
         </FONT>
      </TD>
   </TR>
   <TR>
      <TD COLSPAN="4">
         <INPUT NAME="reset" TYPE="reset" VALUE="Clear Form">
         <INPUT NAME="cmdPrevious" TYPE="button" VALUE="Back" 
                onClick="history.back()">
         <INPUT NAME="Submit" TYPE="submit" VALUE="Continue">
      </TD>
   </TR>

   </TABLE>
   </DIV>
</FORM>
</BODY>
</HTML>

Save the page as CheckoutCredit.asp

Validating the User's Details

Our next task is to create the checkout_validate.inc file we have included in both the personal details page and the credit card info page.

It contains four client-side functions, the first of which is numericOnly. This function goes through each character in a string and checks to see if it's a valid character or not ­- as specified by sValidChars. If it's not valid (i.e. not a number), the character is removed and when all characters have been checked, the function returns what's left.

<script language="JavaScript">
 
// Removes all characters which are not digits
// from a string
function numericOnly(sString)
{
   var sNumericOnly = "";
   var sValidChars = "1234567890";
   for (var iCharPos = 0; iCharPos < sString.length; iCharPos++)
   {
      if (sValidChars.indexOf(sString.charAt(iCharPos)) != -1)
      {
         sNumericOnly = sNumericOnly + sString.charAt(iCharPos);
      }
   }
   return sNumericOnly;
}

Note that if we didn't have to worry about version 3 browsers, we could make good use of the version 4 browsers' support for JavaScript 1.2 and replace the function with the line:

sString = sString.replace(/(\D)+/g,"")

Visual Basic developers will recognize the next function we create which trims all white space - tab, space, and line feed - characters from the beginning and end of a string. In effect this is the JavaScript equivalent of the VB trim statement.

Our trim function works by looping through from the start of the string checking each character to see if it's white space or not. If it hits a non-whitespace character it breaks out of the loop and we have found the start of the valid string. The same algorithm, but starting from the end of the string, finds the last valid character at the end of the string.

// Removes all whitespace characters
// from start and end of a string
function trim(sString)
{
   sTrimmedString = "";
   if (sString != "")
   {

      var iStart = 0;
      var iEnd = sString.length - 1;
      var sWhitespace = " \t\f\n\r\v";
      
      while (sWhitespace.indexOf(sString.charAt(iStart)) != -1)
      {
         iStart++;
         if (iStart > iEnd)
            break;
      }
      
      // If the string not just whitespace
      if (iStart <= iEnd)
      {
         while (sWhitespace.indexOf(sString.charAt(iEnd)) != -1)
            iEnd--;
         sTrimmedString = sString.substring(iStart,++iEnd);
      }
   }
   return sTrimmedString;
}

Again, using regular expressions and the string object's replace method, the whole function could be achieved in two lines.

sString = sString.replace(/^[\s]+/g,"");
sString = sString.replace(/[\s]+$/g,"");

Our third function ensures that the user has completed all the form elements. It loops through each element in the Form.Elements[] collection, which can be abbreviated to Form[], and if it's an text or radio element, it checks it has a value. For radio button groups we need to loop though each radio button in the group and check to see if one has been selected. The naming convention I have used for radio buttons is to prefix the name with rad. To let the user know which element has failed validation the name of the radio button can be used with the rad prefix removed to make it more readable.

// Checks all text boxes and radio button groups
// have a VALUE entered
function checkCompleted(theForm)
{
   var bRadioChecked;
   var sElementGroupName;
   var theElement;
   
   // loop through all elements on form
   for (var iElement = 0; iElement < theForm.length;iElement++)
   {   
      theElement = theForm[iElement];
      
      // <INPUT TYPE="TEXT">
      if (theElement.TYPE == "text")
      {
         if (trim(theElement.VALUE) == "")
         {
            alert("You must complete all the form details");
            theElement.focus();
            theElement.select();
            return false;
         }
      }

      // <INPUT TYPE="RADIO">
      else if (theElement.TYPE == "radio")
      {
         bRadioChecked = false;
         sElementGroupName = theElement.NAME;
 
         // all radio buttons in a group have the same NAME
         // so loop through all radio elements with same NAME
         // until one true or last one reached
         while (theElement.NAME == sElementGroupName)
         {
            if (theElement.checked == true)
            {
               bRadioChecked = true;
            }
            iElement++;
            theElement = theForm[iElement];
         }
         
         if (bRadioChecked == false)
         {
            // radio button names in form radCreditCard
            // so just cut off first 3 characters
            alert("Please select your " + _
               sElementGroupName.substring(3,sElementGroupName.length));
            return false;
         }
         iElement--;
      }
   }
   return true;
}

The final validation routine checks our cboExpMonth and cboExpYear select elements that make up the card expiry date to see that the card date has not already expired. However, we encounter a problem here in that the values returned by the Date object in JavaScript are particularly platform and browser dependent - some browsers return 99 as the year, others the full 4 digits 1999. Here we get round the problem by assuming the year 2000 if the value returned by the getYear() method is 0 or by simply adding 1900 if it's another value below 1900. Note that if we were using JavaScript 1.3 (IE5, NC4.06+) or JScript5, the getFullYear() method of the Date object would solve this problem.

If the current year is the same as the year the user selected and the month is before the current month then we know the card has expired and we inform the user.

// Checks card not expired already
function checkCardExpDate(cboExpMonth,cboExpYear)
{
   var nowDate = new Date();
   var nowYear = nowDate.getYear();
   var nowMonth = nowDate.getMonth() + 1;
   var expYear = cboExpYear.options[cboExpYear.selectedIndex].VALUE;
   var expMonth = cboExpMonth.options[cboExpMonth.selectedIndex].VALUE;
   
   // some browsers return only 99 for the year so we need
   // to compensate for that
   if (nowYear == 0)
   {
      nowYear = 2000;
   }
   if (nowYear < 1900)
   {
      nowYear = nowYear + 1900;
   }
   if (expYear <= nowYear)
   {
      if (expMonth < nowMonth)
      {
         alert("According to the date you have entered, _
                your credit card has expired")
         cboExpMonth.focus();
         return false;
      }
   }
}
</SCRIPT>

Save this file as checkout_validate.inc.

The End - A Final Summary of the Order Details

The final page, before the user commits to purchasing, is the summary page. We have all the details we need to complete the order and we are giving the customer one last chance to check the details before sending their order.

The form contains all the information the user has entered and will be passed in the final form submit. The information obtained from the previous forms is placed at the top of the page in hidden text boxes whose values we populate using server-side JScript.

<!--#include file="ServerSideGlobalDef.inc"-->
<HTML>
<HEAD>
   <TITLE>Confirm Details</TITLE>
</HEAD>
 
<BODY>
<FORM ACTION="ProcessOrder.asp" method="POST">
 
   <!-- Name/Address Details -->
   <INPUT TYPE="HIDDEN" NAME="txtTitle"  
          VALUE="<%=Request.Form("txtTitle")%>">
   <INPUT TYPE="HIDDEN" NAME="txtFirstName" 
          VALUE="<%=Request.Form("txtFirstName")%>">
   <INPUT TYPE="HIDDEN" NAME="txtLastName" 
          VALUE="<%=Request.Form("txtLastName")%>">
   <INPUT TYPE="HIDDEN" NAME="txtEmail" 
          VALUE="<%=Request.Form("txtEmail")%>">
   <INPUT TYPE="HIDDEN" NAME="txtStreet" 
          VALUE="<%=Request.Form("txtStreet")%>">
   <INPUT TYPE="HIDDEN" NAME="txtCity" 
          VALUE="<%=Request.Form("txtCity")%>">
   <INPUT TYPE="HIDDEN" NAME="txtLocality"  
          VALUE="<%=Request.Form("txtLocality")%>">
   <INPUT TYPE="HIDDEN" NAME="txtPostCode" 
          VALUE="<%=Request.Form("txtPostCode")%>">
   <INPUT TYPE="HIDDEN" NAME="txtCountry" 
          VALUE="<%=Request.Form("txtCountry")%>">

   <!-- Credit Card Details -->
   <INPUT TYPE="HIDDEN" NAME="txtCCHolderName" 
          VALUE="<%=Request.Form("txtCardHolderName") %>">
   <INPUT TYPE="HIDDEN" NAME="txtCCNo" 
          VALUE="<%=Request.Form("txtCardNo") %>">
   <INPUT TYPE="HIDDEN" NAME="txtCCType" 
          VALUE="<%=Request.Form("radCardType") %>">
   <INPUT TYPE="HIDDEN" NAME="txtCCExpire" 
          VALUE="<%=Request.Form("cboExpMonth") + "/" + _
                 Request.Form("cboExpYear") %>">

Our next task is to display a summary of the information the user entered starting with the actual items in the order. We use the Basket.inc file we created earlier (and used for the shopping basket) to actually display the summary, this time we want it to be read only so bReadOnly is set to true. The Basket.inc file has hidden input elements with the ItemId's and quantities of the order and these will be sent when the form is submitted.

   <!-- Summarize Order details -->
   <FONT FACE="Comic Sans MS" SIZE="+1" color="Navy">
      <P>Your order details are listed below.</P>
      <P>
         Once you have confirmed the details click
         <INPUT TYPE="Submit" NAME="cmdSubmit" VALUE="Submit Order">
         to send your order
      </P>
   </FONT>
   <STRONG><FONT FACE="Comic Sans MS" SIZE="3" color="#FF8040">
      <br>The following items<br><br>
   </FONT></STRONG>
 
   <!-- Summary of items in order -->
<%
   bReadOnly = true; 
%>
   <!--#include file="Basket.inc"-->
   <STRONG><FONT FACE="Comic Sans MS" SIZE="3" color="#FF8040">
      Will be delivered to<br>
   </FONT></STRONG>

The next summary we display is that of the customer's name and address details which we format by placing inside a table. The values are populated by ASP script which retrieves them from those posted in the form submit that brought us to this page.

   <!-- Summary of NAME and address for delivery -->
   <TABLE cellspacing="2" cellpadding="2" border="0">
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">        
            <%=Request.Form("txtTitle")%> 
            <%=Request.Form("txtFirstName")%> 
            <%=Request.Form("txtLastName")%>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("txtStreet")%>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>
      <TD>

         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("txtCity")%>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("txtLocality")%>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("txtPostCode")%>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("txtCountry")%>
         </FONT></STRONG>
      </TD>
   </TR>
   </TABLE>

The summary is completed with a summary of the credit card details and a restating of exactly how much will be debited from the card.

   <!-- Summary of amount to be charged to credit card -->
   <br>
   <STRONG><FONT FACE="Comic Sans MS" SIZE="3" color="#FF8040">
      A total of <FONT color="Black">£<%=lTotal + 2.5 %></FONT> 
      will be debited from your <%=Request.Form("radCardType")%> card 
      (Card details below)
   </FONT></STRONG>
 
   <!-- Show summary of card details -->
   <TABLE>
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            Name of credit card holder : 
         </FONT></STRONG>
      </TD>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("txtCardHolderName")%>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            Card Number
         </FONT></STRONG>
      </TD>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%= Request.Form("txtCardNo") %>
         </FONT></STRONG>
      </TD>
   </TR>
   <TR>

      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            Expiry Date
         </FONT></STRONG>
      </TD>
      <TD>
         <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
            <%=Request.Form("cboExpMonth")%> / _
            <%=Request.Form("cboExpYear") %>
         </FONT></STRONG>
      </TD>
   </TR>
   </TABLE>
 
   <STRONG><FONT FACE="Comic Sans MS" SIZE="2">
      Click 
      <INPUT TYPE="Submit" NAME="cmdSubmitBottom" VALUE="Purchase items">
      to send your order
   </FONT></STRONG>
</FORM>
</BODY>
</HTML>

Save the page as CheckoutConfirm.asp

Check out the Checkout

Before continuing it's worth testing the checkout code so far before we move on to the order processing.

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.

“In theory, theory and practice are the same. In practice, they're not.”