Placing An Order

It's taken some time to get to this point, but now we come to the whole object of the exercise. Our Web application has persuaded the user that they want to order one of our cars, and we need to place this order in the showroom and head office databases.

The order process consists of two steps. The first is for the user to select their preferred method of placing the order, via our secure site accessed with a certificate (as introduced in Chapter 7) or through the standard site. The page

weborder.htm
gives them these options, plus the option to jump to the certificate enrollment page where they can obtain a certificate:

The list is created using HTML

<UL>
and
<LI>
elements in the usual way. However there are no hyperlinks, so we add the
STYLE="cursor:hand"
attribute, as well as an
ID
so that we can identify the entire list later in our code. We also give each option its own unique
ID
:

...

<UL ID="theList" STYLE="cursor:hand">

<LI ID="option1">I have the Wrox certificates, and want 

to use the secure site</LI><P>

<LI ID="option2">I don't have the Wrox certificates, 

and will use the standard site</LI><P>

<LI ID="option3">I'll apply for the Wrox certificates now 

and place my order later</LI><P>

</UL>

...

Dynamic Style Changes

As the mouse pointer moves over the list options we use the standard Dynamic HTML technique to change the style of the text to bold red lettering, highlighting the option the mouse pointer is over:

Sub theList_onmouseover()

'make option under cursor bold and red

Set objItem = window.event.srcElement

objItem.style.color = "red"

objItem.style.fontWeight = "bold"

window.event.cancelBubble = True

window.event.returnValue = False

End Sub

Sub theList_onmouseout()

'make option normal when cursor moves off

Set objItem = window.event.srcElement

objItem.style.color = "black"

objItem.style.fontWeight = "normal"

window.event.cancelBubble = True

window.event.returnValue = False

End Sub

Opening The Order Detail Page

When the user clicks on a link we can open the appropriate page in the main frame of our application window. If they select the secure site, this will be the page

placeorder.asp
stored in a directory within that area of our site. If they opt to use the standard site to place an order, this is an identical file within the same unsecured directory as the rest of the application.

To use the secure site, you must apply for the Wrox root and client certificates. You'll need to specify the URL of your own Web site to obtain the client certificate. If you don’t have your own site, you can cheat by specifying a friend's site, or even our own site, but don’t tell anybody else about this.

The

placeorder.asp
file will display text boxes where they enter the information required to place the order. However they've already chosen the car model and color, so we can pre-fill these for them. This means that we need to be able to get at these values from code in the
placeorder.asp
page.

This is not a problem if the page is loaded from the same directory as the other pages (more specifically the frameset page

wroxcars.asp
), because we can get at the global variables
top.selectedModel
,
top.SelectedColor
, etc. However if the page is loaded from a different domain (and, more importantly, a secure
https://
domain) we can’t access variables or code in other pages—the browser security model will prevent this.

This is why we chose to use an ASP page for collecting user details because, in the case of a secure order, we won’t be able to retrieve the global variables from code within it. Instead we'll pass the values to it through the URL

QueryString
. This is the code in the page
weborder.htm
which opens the
placeorder.asp
page in either the secure or normal directory, or redirects the user to the certificate enrollment site:

Sub theList_onclick()

'get array indexes for selected car and color

intCarIndex = top.CarArrayIndex

intColorIndex = top.ColorArrayIndex

'get total price, maybe including finance payments

If top.financeTotal > 0 Then 

curTotalPrice = top.financeTotal

Else

curTotalPrice = top.arrCars(5, intCarIndex)

End If

'build query string to pass values on to placeorder.asp page

strQuery = "?CarID=" & top.selectedModel _

& "&CarName=" & top.arrCars(1, intCarIndex) _

& "&ColorID=" & top.selectedColor _

& "&ColorName=" & top.arrColors(2, intColorIndex) _

& "&TotalPrice=" & curTotalPrice

'jump to appropriate page depending on item selected

strItem = window.event.srcElement.id

Select Case strItem

Case "option1": window.location.href = _

"https://rapid.wrox.co.uk/securesite/placeorder.asp" & strQuery

Case "option2": window.location.href = "placeorder.asp" & strQuery

Case "option3": top.window.location.href = "/certsrv/"

End Select

window.event.cancelBubble = True

End Sub

This code creates a query string

strQuery
, and adds it onto the end of the URL used for placing an order. The string itself will contain the key values for the car model and color, the text names of the car model and color, and the total price including any finance payments. Depending on the user selections, it will look something like this:

placeorder.asp?CarID=4&CarName=Hardy S Coupe&ColorID=4

&ColorName=Hot Pink&TotalPrice=30331

We could have tested for the presence of certificates and redirected the user automatically to the appropriate site, but this would be more complex. Normally the browser doesn’t send any certificates, and the server doesn’t request them. It would mean that we would have to use a different server directory that requested certificates, and then redirected the client back to the secure site that requires them.

Pre-filling The Order Details

The

placeorder.asp
files in the secure and normal directories are identical. Their task is to collect the rest of the details required to place the order from the user, and pass these on to our custom business functions back on the server which will place the order in the showroom database and post a message off to head office as well—in exactly the same way as the showroom application we saw in Chapter 6 did. Because of the way we designed the applications for this book, we can interchange the client without making any changes to the 'back end' services.

The HTML part of the page is simple enough. Note how we use the

READONLY
attribute to prevent the user changing the car, color or price information, and we include hidden fields for the car and color
IDs
(the key values). We also have a hidden field that is pre-filled with the word Anonymous for the salesperson's name, just so that we get a value sent to the order processing components:

<%@ LANGUAGE="VBSCRIPT" %>

...

<FORM ID="frmOrder" ACTION="WCCOrderQ.asp" METHOD="POST">

<TABLE>

<TR>

<TD STYLE="text-align:right">Vehicle Name:</TD>

<TD STYLE="text-align:left">

<INPUT TYPE=TEXT SIZE=20 READONLY NAME="CarName">

<INPUT TYPE=TEXT NAME="CarID" STYLE="visibility:hidden; width:0">

</TD>

</TR>

... { code for the rest of the HTML controls here }

<TR>

<TD STYLE="text-align:right">Phone:</TD>

<TD STYLE="text-align:left"><INPUT TYPE=TEXT NAME=Phone SIZE=20></TD>

</TR>

<TR>

<TD COLSPAN=2 STYLE="text-align:right">

<INPUT TYPE="BUTTON" ID="cmdOrder" VALUE="Place Order" 

ONCLICK="submitOrder()" TITLE="Place your order now">

</TD>

</TR>

</TABLE>

</FORM>

Pre-filling the Order Details

This is an ASP page, and we are sending it a query string containing the values we want filled in for some of the controls. We could write these values into the HTML as part of the

<INPUT>
elements, but we chose to do it with some client-side script that runs when the page is loaded:

Sub window_onload()

'fill in the car and color details from the query string

document.all("CarName").Value = "<% = Request.QueryString("CarName") %>"

document.all("CarID").Value = "<% = Request.QueryString("CarID") %>"

document.all("ColorName").Value = _

"<% = Request.QueryString("ColorName") %>"

document.all("ColorID").Value = "<% = Request.QueryString("ColorID") %>"

document.all("TotalPrice").Value = _

"<% = CLng(Request.QueryString("TotalPrice")) %>"

<% 

'If cePresent (1) of Flags is set we have a client certificate

If (Request.ClientCertificate("Flags") And 1) Then 

%>

document.all("Name").Value = _

"<% = Request.ClientCertificate("SubjectCN") %>"

document.all("Town").Value = _

"<% = Request.ClientCertificate("SubjectL") %>"

document.all("State").Value = _

"<% = Request.ClientCertificate("SubjectS") %>"

<% 

End If 

%>

End Sub

This produces a

window_onload()
subroutine in the page, which looks like the code below. Because the user chose the 'secure ordering' option, we can get some details from their client certificate as well:

Sub window_onload()

'fill in the car and color details from the query string

document.all("CarName").Value = "Hardy S Coupe"

document.all("CarID").Value = "4"

document.all("ColorName").Value = "Hot Pink"

document.all("ColorID").Value = "4"

document.all("TotalPrice").Value = "30331"

document.all("Name").Value = "Alex Homer"

document.all("Town").Value = "Stonebroom"

document.all("State").Value = "Derbyshire"

End Sub

Here's the result when we actually did find someone who wanted to buy a pink car:

Submitting The Order

The final section of the

placeorder.asp
page is a client-side routine that submits the order to our custom business objects when the Place Order button is clicked. If you look back at the HTML code of this page, you'll see that even though all the controls are on a
<FORM>
, the button isn’t a
SUBMIT
button—it just runs our custom
submitOrder
procedure:

<INPUT TYPE="BUTTON" ID="cmdOrder" VALUE="Place Order" 

ONCLICK="submitOrder()" TITLE="Place your order now">

The

submitOrder
procedure checks that we got at least some input in each text box (except for the Phone box) and if not, displays a message. If everything else is OK, it submits the
<FORM>
to the same ASP page as we used in our showroom Web application,
WCCOrderQ.asp
, by calling the
submit
method of the form:

Sub submitOrder()

blnOK = True  'check we got enough details

If document.all("Name").Value = "" Then blnOK = False

If document.all("Address").Value = "" Then blnOK = False

If document.all("Town").Value = "" Then blnOK = False

If document.all("State").Value = "" Then blnOK = False

If document.all("ZipCode").Value = "" Then blnOK = False

If Not blnOK Then 

strMesg = "Only the 'Phone' field is optional."

MsgBox strMesg, vbInformation, "More Details Required"

End If

'submit the form to the ASP order script

If blnOK Then document.all("frmOrder").submit

End Sub

At this point, the

WCCOrderQ.asp
page that we wrote in Chapter 6 takes over, and the order is registered with head office. Within a few days, our customer should be the proud possessor of a hot pink Hardy S. Coupe...

© 1998 by Wrox Press. All rights reserved.