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
gives them these options, plus the option to jump to the certificate enrollment page where they can obtain a certificate:weborder.htm
The list is created using HTML
and <UL>
elements in the usual way. However there are no hyperlinks, so we add the <LI>
attribute, as well as an STYLE="cursor:hand"
so that we can identify the entire list later in our code. We also give each option its own unique ID
: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
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.placeorder.asp
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
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.placeorder.asp
This is not a problem if the page is loaded from the same directory as the other pages (more specifically the frameset page
), because we can get at the global variables wroxcars.asp
, top.selectedModel
, etc. However if the page is loaded from a different domain (and, more importantly, a secure top.SelectedColor
domain) we can’t access variables or code in other pages—the browser security model will prevent this. https://
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
. This is the code in the page QueryString
which opens the weborder.htm
page in either the secure or normal directory, or redirects the user to the certificate enrollment site:placeorder.asp
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
, 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:strQuery
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
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.placeorder.asp
The HTML part of the page is simple enough. Note how we use the
attribute to prevent the user changing the car, color or price information, and we include hidden fields for the car and color READONLY
(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:IDs
<%@ 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
elements, but we chose to do it with some client-side script that runs when the page is loaded:<INPUT>
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
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:window_onload()
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
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 placeorder.asp
, the button isn’t a <FORM>
button—it just runs our custom SUBMIT
procedure:submitOrder
<INPUT TYPE="BUTTON" ID="cmdOrder" VALUE="Place Order"
ONCLICK="submitOrder()" TITLE="Place your order now">
The
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 submitOrder
to the same ASP page as we used in our showroom Web application, <FORM>
, by calling the WCCOrderQ.asp
method of the form: submit
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
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...WCCOrderQ.asp