Figure 4   search.asp

<%

' Determine initial view for the page.
If UCase(Request.QueryString("VIEW")) = "ADVANCED" Then
    initialView = "advanced"
Else
    initialView = "basic"
End If

' Set the page to expire immediately
Response.Expires = 0

' Create the ADO connection for the HTML SELECTs
Set Books = Server.CreateObject("ADODB.Connection")
Books.ConnectionTimeout = 30
Books.CommandTimeout = 15
Books.Open "DSN=MSPRESS;SERVER=MSPRESS;UID=dbAdmin;DATABASE=CommerceServer;" _
    Trusted_Connection=Yes","dbAdmin",""
Set cmdTemp = Server.CreateObject("ADODB.Command")

' Get a recordset for the Categories
Set Subject = Server.CreateObject("ADODB.Recordset")
cmdTemp.CommandText = "SELECT SUBJECT_NAME, SUBJECT_ID FROM MSPRESS30_SUBJECT " _
    ORDER BY SUBJECT_NAME"
cmdTemp.CommandType = 1
Set cmdTemp.ActiveConnection = Books
Subject.Open cmdTemp, , 3, 1

' Get a recordset for the Keywords (Recipe Attributes)
Set Author = Server.CreateObject("ADODB.Recordset")
cmdTemp.CommandText = "SELECT LAST_NAME, FIRST_NAME, AUTHOR_ID FROM " _
    MSPRESS30_AUTHOR ORDER BY LAST_NAME, FIRST_NAME"
cmdTemp.CommandType = 1
Set cmdTemp.ActiveConnection = Books
Author.Open cmdTemp, , 3, 1

' Make sure that IE4 is the client%>
<!--#INCLUDE FILE="checkIE4.asp"--><HTML>
<HEAD>
<STYLE>
    a:active {
        text-decoration:none;
        color:#FF0000    
    }
    .headerItem1 {
        color:#FFFFFF;
        background:#000000;
        font:bold 25 'courier new'
    }
    .headerItem2 {
        color:#FFFFFF;
        background:#000000;
        font:bold 16 'courier new'
    }
    .headerButtonDown {
        cursor:hand;
        color:#FFFFFF;
        border:1px inset;
        font:10 'ms sans serif'
    }
    .headerButtonUp {
        cursor:hand;
        color:#FFFFFF;
        border:1px outset;
        font:10 'ms sans serif'
    }
    .headerButtonNormal {
        cursor:hand;
        color:#FFFFFF;
        border:1px solid #000000;
        font:10 'ms sans serif'
    }
    .cellItem {
        font:10 'ms sans serif'
    }
</STYLE>
<TITLE>Book Search Page</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var badISBN = false;
var currentView = "<%=initialView%>";
var pageReset = false;

/*
 *  This function handles the initialization of the page.
 */
function startPage() {
    loadDefaults();
// Set the passed-in value (so we can return to the current view if needed)
    document.all.item("VIEW").value = "<%=initialView%>"; 
// Change the view to the correct one
    document.all.item("<%=initialView%>Button").click(); 
// Make the document visible
    document.all.item("BODYTAG").style.visibility = "visible"; 
}

/*  This function loads the default form values. */
function loadDefaults() {<%
// Set the default Title
If Len(Request.QueryString("TITLE")) > 0 Then%>
    document.all.item("TITLE").value = _ 
        "<%=Replace(Request.QueryString("TITLE"),"""","\""")%>";
<%
End If

// Set the Title search to the correct type
If Len(Request.QueryString("TC")) > 0 Then%>
    document.all.item("TC").value = "<%=Request.QueryString("TC")%>";
<%
End If

// Set the default Subject (Document Name)
If Len(Request.QueryString("SUBJECT")) > 0 Then%>
    document.all.item("SUBJECT").value = _
        "<%=Replace(Request.QueryString("SUBJECT"),"""","\""")%>"; 
<%
End If

// Set the default Author (Document Name)
If Len(Request.QueryString("AUTHOR")) > 0 Then%>
    document.all.item("AUTHOR").value = _
        "<%=Replace(Request.QueryString("AUTHOR"),"""","\""")%>"; 
<%
End If

// Set the default ISBN (Document Name)
If Len(Request.QueryString("ISBN")) > 0 Then%>
    document.all.item("ISBN").value = _
        "<%=Replace(Request.QueryString("ISBN"),"""","\""")%>"; <%
End If

// Default sortby option
If Len(Request.QueryString("SORTBY")) > 0 Then%>
    document.all.item("SORTBY").value = "<%=Request.QueryString("SORTBY")%>"; 
<%
End If

// Default initial order by option
If Len(Request.QueryString("ORDER")) > 0 Then%>
    document.all.item("ORDER").value = "<%=Request.QueryString("ORDER")%>"; 
<%
End If

// Default the maximum number of items to return
If Len(Request.QueryString("MAXROWS")) > 0 Then%>
    document.all.item("MAXROWS").value = "<%=Request.QueryString("MAXROWS")%>";
<%
End If

// Default the number of items to display per page
If Len(Request.QueryString("PS")) > 0 Then%>
    document.all.item("PS").value = "<%=Request.QueryString("PS")%>"; 
<%
End If
%>
}

/* Handle the button appearance when rolling over a button. */

function rollon(itemName) {
    if (itemName.className == "headerButtonNormal") {
// Switch the class to highlight the button
        itemName.className = "headerButtonUp"; 
    }
    window.event.cancelBubble = true;
}

/* This function handles the button appearance when rolling off of a button. */
function rolloff(itemName) {
    if (itemName.className == "headerButtonUp") {
 // Switch the class of the button back to normal
        itemName.className = "headerButtonNormal";
    }
    window.event.cancelBubble = true;
}

/* Handle the view flipping within the page after the page is loaded. */

function switchViews(itemName) {
    var viewMode = itemName.id.substring(0,itemName.id.indexOf("Button"));
    document.all.item(currentView+"Button").className = "headerButtonNormal";
    currentView = viewMode;
    document.all.item(currentView+"Button").className = "headerButtonDown";
    document.all.item("formHolder").style.visibility = "hidden";
    document.all.item("formHolder").filters.item(0).apply();
// Transition 5 causes a computer to look slow.  (Maybe a good thing.)
//    document.all.item("formHolder").filters.item(0).transition = 5;

    document.all.item("formHolder").filters.item(0).transition = 12;
    document.all.item("formHolder").style.visibility = "visible";
    document.all.item("formHolder").filters(0).play(1);
    if (currentView == "advanced") {
        document.all.item("advancedOptions").style.display = "";
        if (!pageReset) {
            document.all.item("VIEW").value = "advanced";
            // Set the value ot be passed in the form 
        }
    } else {
        document.all.item("advancedOptions").style.display = "none";
        if (!pageReset) {
            document.all.item("VIEW").value = "basic";
            // Set the value ot be passed in the form
        }
    }
}

function formatISBN(ISBN) {
    ISBN = trim(ISBN);
    var regISBN = /^\d-\d{5}-\d{3}-\w$/;
    if (regISBN.test(ISBN)) {
        document.all.item("ISBN").value = ISBN;
    } else {
        reFormatISBN(ISBN);
    }
}

function reFormatISBN(ISBN) {
    if (ISBN.length == 10) {
        document.all.item("ISBN").value = ISBN.substr(0,1) + '-' + ISBN.substr(1,5)
            + '-' + ISBN.substr(6,3) + '-' + ISBN.substr(9,1);
    } else {
        badISBN = true;
        alert("You have entered an invalid ISBN number.\n\t- ISBN numbers must be
              10 characters long.\n\t- The first 9 characters must be digits.\n\t-
              The last character can be a digit or a number.");
        document.all.item("ISBN").focus();
    }
}

function trim(item) {
    worker = new String(item);
    if (worker.indexOf(" ") != -1) {
        if (worker.indexOf(" ") == 0) {
            worker = worker.substring(1,worker.length);
            trim(worker);
        }
    }
    if (worker.lastIndexOf(" ") != -1) {
        if (worker.lastIndexOf(" ") >= worker.length-1) {
            worker = worker.substring(0,worker.length-1);
            trim(worker);
        }
    }
    return worker;
}

function checkISBN() {
    if (badISBN) {
        document.all.item("ISBN").value = "";
    }
    document.all.item("SEARCHFORM").submit();
}

/*
 *  This function resets the form.
 */
function resetForm() {
    pageReset = true;
    document.all.item("SEARCHFORM").reset();
    document.all.item("VIEW").value = currentView;
}
</SCRIPT>
</HEAD>

<BODY TOPMARGIN="0" LEFTMARGIN="0" onload="startPage()">
<DIV ID="BODYTAG" STYLE="visibility:hidden">
<TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0">
<TR>
    <TD ALIGN="CENTER" CLASS="headerItem1"><NOBR>Book Search</NOBR></TD>
    <TD ALIGN="RIGHT" WIDTH="20%" CLASS="headerItem1">
        <TABLE BORDER="0" CELLSPACING="0" WIDTH="100%">
            <TR onclick="switchViews(window.event.srcElement)" 
                onmouseover="rollon(window.event.srcElement)" 
                onmouseout="rolloff(window.event.srcElement)">
            <TD WIDTH="50%" ALIGN="CENTER" ID="basicButton" 
                CLASS="headerButtonNormal">basic</TD>
            <TD WIDTH="50%" ALIGN="CENTER" ID="advancedButton" 
                CLASS="headerButtonNormal">advanced</TD>
            </TR>
        </TABLE>
    </TD>
</TR>
</TABLE>

<DIV ID="formHolder" STYLE="position:relative;top:0;left:0;height:25;
    filter:revealTrans(duration=3.0,transition=0)">
<TABLE BORDER="0" COLS="2" CELLSPACING="0">
<FORM ACTION="searchresults.asp" METHOD="GET" ID="SEARCHFORM"
    onsubmit="checkISBN()">
<INPUT TYPE="HIDDEN" NAME="VIEW"></INPUT>

<TR>
    <TD ALIGN="RIGHT" VALIGN="BASELINE" CLASS="cellItem"><NOBR><B>Subject
    </B>&#160;</NOBR></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
        <SELECT NAME="SUBJECT" SIZE="1">
            <OPTION VALUE="">All Subjects</OPTION><%
Do until Subject.EOF%>
            <OPTION VALUE="<%=Subject("SUBJECT_ID")%>">
            <%=Server.HTMLEncode(Subject("SUBJECT_NAME"))%>
</OPTION><%
Subject.MoveNext
Loop%>
        </SELECT>
    </TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="BASELINE" CLASS="cellItem"><NOBR>
   <B>Author</B>&#160;</NOBR></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
        <SELECT NAME="AUTHOR" SIZE="1">
            <OPTION VALUE="">All Authors</OPTION><%

Do until Author.EOF
    If Len(Trim(Author("FIRST_NAME"))) > 0 Then%>
            <OPTION VALUE="<%=Author("AUTHOR_ID")%>"><%=Author("LAST_NAME")&",
            "&Author("FIRST_NAME")%></OPTION><%
    Else%>
            <OPTION VALUE="<%=Author("AUTHOR_ID")%>"><%=Author("LAST_NAME")%>
            </OPTION><%
    End If
Author.MoveNext
Loop
Set Books = nothing%>
        </SELECT>
    </TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="BASELINE" CLASS="cellItem"><NOBR><B>Title</B>&#160;
</NOBR></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
    <NOBR>
        <SELECT NAME="TC" SIZE="1">
            <OPTION VALUE="C" SELECTED>Contains</OPTION>
            <OPTION VALUE="B">Begins with</OPTION>
        </SELECT>&#160;<B>the word(s)</B>&#160;
        <INPUT TYPE="TEXT" NAME="TITLE" SIZE="30"></INPUT>
    </NOBR>
    </TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="BASELINE" CLASS="cellItem"><NOBR><B>ISBN</B>&#160;
    </NOBR></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
        <INPUT TYPE="TEXT" NAME="ISBN" SIZE="13" MAXLENGTH="13" 
          onchange="formatISBN(this.value)"></INPUT>&#160;(E.g.; 1-23456-789-0)
    </TD>
</TR>    
</TABLE>

<DIV CLASS="cellItem" AlIGN="CENTER" ID="advancedOptions">
<HR WIDTH="100%" SIZE="3" NOSHADE COLOR="#000000">
<TABLE BORDER="0" COLS="2" CELLSPACING="0" CELLPADDING="0" WIDTH="100%">
<TR>
    <TD ALIGN="CENTER" CLASS="headerItem2"><NOBR>Advanced Options</NOBR></TD>
    <TD ALIGN="CENTER" CLASS="cellItem">
        <NOBR>
        <B>Sort</B> the results by 

        <SELECT NAME="SORTBY" SIZE="1">
            <OPTION VALUE="SUBJECT" SELECTED>Subject</OPTION>
            <OPTION VALUE="AUTHOR">Author</OPTION>
            <OPTION VALUE="TITLE">Title</OPTION>
        </SELECT> in 

        <SELECT NAME="ORDER" SIZE="1">
            <OPTION VALUE="" SELECTED>ascending</OPTION>
            <OPTION VALUE="DESC">descending</OPTION>
        </SELECT> order.
        </NOBR>
        <BR></BR>
        <NOBR>
        Show 

        <SELECT NAME="MAXROWS" SIZE="1">
            <OPTION VALUE="25">25</OPTION>
            <OPTION VALUE="50">50</OPTION>
            <OPTION VALUE="100">100</OPTION>
            <OPTION VALUE="250">250</OPTION>
            <OPTION VALUE="500">500</OPTION>
            <OPTION VALUE="1000">1000</OPTION>
            <OPTION VALUE="0" SELECTED>all</OPTION>
        </SELECT> <B> results</B> with a maximum of 

        <SELECT NAME="PS" SIZE="1">
            <OPTION VALUE="10">10</OPTION>
            <OPTION VALUE="20" SELECTED>20</OPTION>
            <OPTION VALUE="30">30</OPTION>
            <OPTION VALUE="40">40</OPTION>
            <OPTION VALUE="50">50</OPTION>
        </SELECT> <B>items per page</B>.
        </NOBR>
    </TD>
</TR>
</TABLE>
</DIV>

<HR WIDTH="100%" SIZE="3" NOSHADE COLOR="#000000">

<DIV ALIGN="CENTER">
    <NOBR>
    <INPUT TYPE="SUBMIT" VALUE="Search"></INPUT>&#160;
    <INPUT TYPE="BUTTON" VALUE="Reset" onclick="resetForm()"></INPUT>
    </NOBR>
    <HR WIDTH="100%" SIZE="3" NOSHADE COLOR="#000000">
</DIV>
</FORM>
</DIV>
</BODY>
</HTML>

Figure 6   moreinfo.asp

<%

' Make sure that the client is IE4%>
<!--#INCLUDE FILE="checkIE4.asp"-->
<%
If Len(Request.QueryString("SKU")) > 0 Then
    Set Books = Server.CreateObject("ADODB.Connection")
    Books.ConnectionTimeout = 30
    Books.CommandTimeout = 15
    Books.Open "DSN=MSPRESS;SERVER=MSPRESS;UID=dbAdmin;DATABASE=CommerceServer;" _
        Trusted_Connection=Yes", "dbAdmin",""

    Set cmdTemp = Server.CreateObject("ADODB.Command")
    Set Items = Server.CreateObject("ADODB.Recordset")
    cmdTemp.CommandText = "SELECT mspress30_author.last_name, " _
        "mspress30_author.first_name, mspress30_subject.subject_name, " _
        "mspress30_product.title, mspress30_product.isbn, " _
        "mspress30_product.list_price, mspress30_product.subtitle, " _
        "mspress30_product.long_description, mspress30_product.date_published, " _
        "mspress30_product.publisher, mspress30_product.bookdisk FROM " _
        "mspress30_product INNER JOIN mspress30_author ON " _
        "mspress30_product.author_id = mspress30_author.author_id INNER JOIN " _
        "mspress30_subject ON mspress30_product.subject_id = " _
        "mspress30_subject.subject_id WHERE " _
        "mspress30_product.sku = '"&Request.QueryString("SKU")&"'"
    cmdTemp.CommandType = 1
    Set cmdTemp.ActiveConnection = Books
    Items.Open cmdTemp, , 3, 1%>
<HTML>
<HEAD>
<TITLE>More Information for <%=Items("TITLE")%></TITLE>
<STYLE>
<STYLE>
    a:active {
        text-decoration:none;
        color:#FF0000    
    }
    .headerItem {
        color:#FFFFFF;
        background:#000000;
        font:bold 25 'courier new'
    }
    .cellItem {
        font:10 'ms sans serif'
    }
</STYLE>
</HEAD>

<BODY TOPMARGIN="0" LEFTMARGIN="0">
<TABLE WIDTH=100% CELLSPACING="0" BORDER="0">
<TR>
    <TD COLSPAN=2 ALIGN="CENTER" CLASS="headerItem">More Information</TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Title:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
    <%=Items("TITLE")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Subtitle:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
    <%=Items("SUBTITLE")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Author:</B></TD><%
    If Len(Trim(Items("FIRST_NAME"))) > 0 Then%>
        <TD ALIGN="LEFT" CLASS="cellItem">
        <%=Items("LAST_NAME")%></TD><%
    Else%>
        <TD ALIGN="LEFT" CLASS="cellItem">
        <%=Items("LAST_NAME")&", "&Items("FIRST_NAME")%>
        </TD><%
    End If%>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Subject:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><%=Items("SUBJECT_NAME")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Abstract:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><%=Items("LONG_DESCRIPTION")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Media:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><%=Items("BOOKDISK")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>ISBN:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><%=Items("ISBN")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Publisher:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><%=Items("PUBLISHER")%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Price:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">$<%=Items("LIST_PRICE")/100%></TD>
</TR>
<TR>
    <TD ALIGN="RIGHT" VALIGN="TOP" CLASS="cellItem">
    <B>Publication Date:</B></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><%=Items("DATE_PUBLISHED")%></TD>
</TR>
</TABLE>
<HR WIDTH="100%" SIZE="3" NOSHADE COLOR="#000000">
</BODY>
</HTML><%
Else
    Response.Redirect Left(Request.ServerVariables("PATH_INFO"), _
        InStrRev(Request.ServerVariables("PATH_INFO"), "/"))
End If%>

Figure 7   searchresultsdata.asp

<%
'''''
'
' file:  searchresultsdata.asp
'
' description:  This file receives a GET and generates a page of
'               tabular data ot be consumed by the TDC in 
'               searchresults.asp.
'
' arguments:  QueryString = Request.QueryString sets up parameters for
'                           the search
'
' components:  ASP Server Object
'              ASP Request Object
'              ASP Response Object
'              ADO Recordset Object
'              ADO Command Object
'              ADO Connection Object
'
'''''
' Make sure that there is a QueryString coming in.
If Len(Request.QueryString) > 0 Then
    If Len(Trim(Request.QueryString("TITLE"))) > 0 Then
        Select Case UCase(Request.QueryString("TC"))
            Case "B"
                whereClause = whereClause&"mspress30_product.TITLE LIKE '"&Trim(Request.QueryString("TITLE"))&"%' and "
            Case "C"
                whereClause = whereClause&"mspress30_product.TITLE LIKE '%"&Trim(Request.QueryString("TITLE"))&"%' and "
            Case Else
                whereClause = whereClause&"mspress30_product.TITLE = '"&Trim(Request.QueryString("TITLE"))&"' and "
        End Select
    End If
    If Len(Request.QueryString("SUBJECT")) > 0 Then
        whereClause = whereClause&"mspress30_subject.SUBJECT_ID = "&Request.QueryString("SUBJECT")&" and  "
    End If
    If Len(Request.QueryString("AUTHOR")) > 0 Then
        whereClause = whereClause&"mspress30_author.AUTHOR_ID = "&Request.QueryString("AUTHOR")&" and "
    End If
    If Len(Request.QueryString("ISBN")) > 0 Then
        whereClause = whereClause&"mspress30_product.ISBN = '"&Request.QueryString("ISBN")&"' and "
    End If
' Get rid of the whitespace on the ends of the SQL statement where clause
    whereClause = Trim(whereClause)
    If Right(whereClause,3) = "and" Then 'We need to trim the "and" off the end of the SQL statement where clause
        whereClause = Left(whereClause,Len(whereClause)-3)
        whereClause = Trim(whereClause)
    End If

    If Len(whereClause) > 0 Then 'Create the SQL statement where clause
        sqlStatement = "SELECT MSPRESS30_AUTHOR.LAST_NAME AS LAST_NAME, 
MSPRESS30_AUTHOR.FIRST_NAME AS FIRST_NAME, 
MSPRESS30_SUBJECT.SUBJECT_NAME AS SUBJECT, 
MSPRESS30_PRODUCT.TITLE AS TITLE, 
MSPRESS30_PRODUCT.SKU AS SKU,
MSPRESS30_PRODUCT.DATE_PUBLISHED AS PUBDATE, 
MSPRESS30_PRODUCT.LIST_PRICE AS PRICE FROM MSPRESS30_PRODUCT INNER JOIN MSPRESS30_AUTHOR ON 
MSPRESS30_PRODUCT.AUTHOR_ID = MSPRESS30_AUTHOR.AUTHOR_ID INNER JOIN MSPRESS30_SUBJECT ON MSPRESS30_PRODUCT.SUBJECT_ID  = 
MSPRESS30_SUBJECT.SUBJECT_ID WHERE "&whereClause
    Else
        sqlStatement = "SELECT MSPRESS30_AUTHOR.LAST_NAME AS LAST_NAME, MSPRESS30_AUTHOR.FIRST_NAME AS FIRST_NAME, 
MSPRESS30_SUBJECT.SUBJECT_NAME AS SUBJECT, MSPRESS30_PRODUCT.TITLE AS TITLE, MSPRESS30_PRODUCT.SKU AS SKU, 
MSPRESS30_PRODUCT.DATE_PUBLISHED AS PUBDATE, MSPRESS30_PRODUCT.LIST_PRICE AS PRICE FROM MSPRESS30_PRODUCT 
INNER JOIN MSPRESS30_AUTHOR ON MSPRESS30_PRODUCT.AUTHOR_ID = MSPRESS30_AUTHOR.AUTHOR_ID 
INNER JOIN MSPRESS30_SUBJECT ON MSPRESS30_PRODUCT.SUBJECT_ID  = MSPRESS30_SUBJECT.SUBJECT_ID"
    End If

' Setup the maximum number of items to return.
    If Len(Request("MAXROWS")) > 0 Then
        maxRows = Request("MAXROWS")
    Else
        maxRows = 0
    End If

' Do the search.
    Set Books = Server.CreateObject("ADODB.Connection")
    Books.ConnectionTimeout = 30
    Books.CommandTimeout = 15
    Books.Open "DSN=MSPRESS;SERVER=MSPRESS;UID=dbAdmin;DATABASE=CommerceServer;Trusted_Connection=Yes",
"dbAdmin",""
    Set cmdTemp = Server.CreateObject("ADODB.Command")
    Set Items = Server.CreateObject("ADODB.Recordset")
    Items.MaxRecords = maxRows
    cmdTemp.CommandText = sqlStatement
    cmdTemp.CommandType = 1
    Set cmdTemp.ActiveConnection = Books
    Items.Open cmdTemp, , 3, 1

' Tell the browser what's coming from the server (Mimetype).
    Response.ContentType = "text/plain"

' Create the header for the TDC file.
    Response.Write "LastName:String,FirstName:String,Subject:String,Title:String,
    Price:Float,PriceDisplay:String,ViewDocURL:String"
&vbcrlf

' Move through the RecordSet to create the rest of the file.
    Do until Items.EOF

' Get rid of any commas that might be in the fields from the database.
        If Len(Trim(Items("FIRST_NAME"))) > 0 Then
            FirstName = Replace(Items("FIRST_NAME"),",","")
        Else
            FirstName = ""
        End If
        displayPrice = "$"&Left(Items("PRICE"),Len(Items("PRICE"))-2)&"."&Right(Items("PRICE"),2)
         rowItem = Replace(Items("LAST_NAME"),",","")&","&FirstName&","
&Replace(Items("SUBJECT"),",","")&","
&Replace(Items("TITLE"),",","")&","&Items("PRICE")/100&","&displayPrice&",moreinfo.asp?sku="&Items("SKU")
' Get rid of any crlf's that might be in the fields from the database.
        rowItem = Replace(rowItem,vbcrlf,"")

' Write out the line.
        Response.Write rowItem&vbcrlf
        Items.MoveNext
    Loop
    Set Books = Nothing
End If%>

Figure 8   Search Results

LastName:String,FirstName:String,Subject:String,Title:String,Price:Float,
    PriceDisplay:String,ViewDocURL:String
Stroo,Eric,Office,The Ultimate Microsoft&reg; Office
    Book,24.95,$24.95,moreinfo.asp?sku=1
Wells,Eric,Excel,Developing Microsoft&reg; Excel 5
    Solutions,39.95,$39.95,moreinfo.asp?sku=10
Microsoft Corporation,,OLE,OLE 2 Programmer's Reference Volume 
    One,24.95,$24.95,moreinfo.asp?sku=100
Microsoft Corporation,,OLE,OLE 2 Programmer's Reference Volume 
    Two,29.95,$29.95,moreinfo.asp?sku=101
Microsoft Corporation,,Windows,The Windows&#153; Interface: An Application Design
    Guide,39.95,$39.95,moreinfo.asp?sku=103
Microsoft Corporation,,MS-DOS,Microsoft&reg; MS-DOS&reg; Programmer's
    Reference,39.95,$39.95,moreinfo.asp?sku=104
Solomon,Christine,Office,Developing Applications with Microsoft&reg;
    Office,39.95,$39.95,moreinfo.asp?sku=11
Fjermedal,Grant,Simulators,Adventures in Space
    Simulator,22.95,$22.95,moreinfo.asp?sku=118
...

Figure 9   searchresultsbasic.asp

<HTML>
<HEAD>
<TITLE>Search Results</TITLE>
<OBJECT CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83" ID="tdcItems"
    HEIGHT="0" WIDTH="0">
    <PARAM NAME="DataURL" VALUE="searchresultsdata.asp?<%=Request.QueryString%>">
    <PARAM NAME="UseHeader" VALUE="True">
</OBJECT>
<STYLE>
    a:active {
        text-decoration:none;
        color:#FF0000    
    }
    .menuItem {
        color:BUTTONTEXT;
        background-color:BUTTONFACE;
        border:2px outset BUTTONFACE;
        font:10 'ms sans serif';
        cursor:auto
    }
    .rowItem {
        border:8px solid #000000
    }
    .cellItem {
        font:10 'ms sans serif'
    }
</STYLE>
</HEAD>
<BODY TOPMARGIN="0" LEFTMARGIN="0">
<TABLE COLS="5" BORDER="0" CELLSPACING="0" WIDTH="100%" ID="boundTable">
<THEAD>
<TR BGCOLOR="#000000">
    <TD COLSPAN="3">
        <TABLE CELLSPACING="0" CELLPADDING=0 WIDTH=100% BORDER="0">
            <TR>
                <TD ALIGN="CENTER" ID="titleSpace" STYLE="font:bold 50 
                'courier new';color:#FFFFFF"><NOBR>Search Results</NOBR></TD>
            </TR>
        </TABLE>
    </TD>
    <TD COLSPAN="2">
    </TD>
</TR>
<TR>
<!--
Create table headers for each column.
-->
<TH ALIGN="LEFT" NOWRAP CLASS="menuItem" ID="Subject" 
    TITLE="Click here to sort by Subject">Subject&#160;&#160;
<IMG ID="arrowSubject" SRC="images/up.gif" WIDTH="10" HEIGHT="10"
    STYLE="visibility:hidden">&#160;&#160;</TH>
<TH ALIGN="LEFT" WIDTH="40%" NOWRAP CLASS="menuItem" ID="Title" 
    TITLE="Click here to sort by Title">Title&#160;&#160; 
<IMG ID="arrowTitle" SRC="images/up.gif" WIDTH="10" HEIGHT="10"
    STYLE="visibility:hidden">&#160;&#160;</TH>
<TH ALIGN="LEFT" WIDTH="25%" NOWRAP CLASS="menuItem" ID="LastName" 
    TITLE="Click here to sort by Author">Author&#160;&#160;
<IMG ID="arrowLastName" SRC="images/up.gif" WIDTH="10" HEIGHT="10"
    STYLE="visibility:hidden">&#160;&#160;</TH>
<TH ALIGN="LEFT" NOWRAP CLASS="menuItem" ID="Price" 
    TITLE="Click here to sort by Price">Price&#160;&#160;
<IMG ID="arrowPrice" SRC="images/up.gif" WIDTH="10" HEIGHT="10"
    STYLE="visibility:hidden">&#160;&#160;</TH>
<TH ALIGN="LEFT" NOWRAP CLASS="menuItem" ID="HeaderNoHL" 
    TITLE="You cannot sort this column">More info.&#160;</TH>
</TR>
</THEAD>
<TBODY>
<!--
Handle the rollover of the rows (this is basically current record highlighting)
with rollon and rolloff functions.
-->
<TR CLASS="rowItem">
    <TD ALIGN="LEFT" CLASS="cellItem"><SPAN DATAFLD="Subject"></SPAN></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><SPAN DATAFLD="Title" DATAFORMATAS="HTML">
    </SPAN></TD>
    <TD ALIGN="LEFT" CLASS="cellItem"><SPAN DATAFLD="LastName"></SPAN>, 
    <SPAN DATAFLD="FirstName"></SPAN></TD>
    <TD ALIGN="RIGHT" CLASS="cellItem"><SPAN DATAFLD="PriceDisplay"></SPAN></TD>
    <TD ALIGN="CENTER" NOWRAP CLASS="cellItem"><A DATAFLD="ViewDocUrl">
    more info...</A></TD>
</TR>
</TBODY>
<TFOOT>
<TR>
    <TD ALIGN="CENTER" COLSPAN="3" STYLE="font:14 'ms sans serif'"><B>
    <A HREF="search.asp?VIEW=advanced&SUBJECT=&AUTHOR=&TC=C&TITLE=&ISBN=&
        SORTBY=SUBJECT&ORDER=&MAXROWS=0&PS=20" STYLE="text-decoration:
        underline!important"> search again</A></B></TD>
    <TD COLSPAN="2">  </TD>
</TR>
</TFOOT> </TABLE>
</BODY> </HTML>

Figure 10    searchresults.asp

 <%
'''''
'
' file:  searchresults.asp
'
' description:  This file receives a GET and performs a search based on
'               the contents of the GET.  It then displays the results
'               using a Data Source Object (DSO) and handles navigation
'               of the results via JavaScript.
'               This page makes heavy use of DHTML.
'
' arguments:  PS = Items to display per page
'             SORTBY = Column to sort results by
'             ORDER = Direction to sort the results in
'             QueryString = QueryString is passed to DSO
'
' components:  ASP Session Object
'              ASP Server Object
'              ASP Request Object
'              ASP Response Object
'              Tabular Data Control DSO
'
' includes:  checkIE4.asp
'
'''''

' Check for IE4 (or greater)%>
<!--#INCLUDE FILE="checkIE4.asp"-->
<%
' Make sure that search criteria are coming through in the QueryString
' This QueryString will also be passed to searchresultsdata.asp
If Len(Request.QueryString) > 0 Then

' Check to see if the items per page has been specified and set it accordingly
    If Len(Request("PS")) > 0 Then
        itemsPerPage = Request("PS")
    Else
        itemsPerPage = 20
    End If

' Set the default number of columns
        tableColumns = 5

' Set the sort direction based on the input
        If Request.QueryString("ORDER") = "" Then
            order = "+"
        Else
            order = "-"
        End If

' Set the sort column based on the input
        Select Case UCase(Request.QueryString("SORTBY"))
            Case "SUBJECT"
                orderColumn = "Subject"
            Case "AUTHOR"
                orderColumn = "LastName"
            Case Else
                orderColumn = "Title"
        End Select%><HTML>
<HEAD>
<TITLE>Search Results</TITLE>
<OBJECT CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83" ID="tdcItems"
HEIGHT="0" WIDTH="0">
    <PARAM NAME="DataURL" VALUE="searchresultsdata.asp?<%=Request.QueryString%>">
    <PARAM NAME="UseHeader" VALUE="True">
</OBJECT>
<STYLE>
    a:active {
        text-decoration:none;
        color:#FF0000    
    }
    .menuItem {
        color:BUTTONTEXT;
        background-color:BUTTONFACE;
        border:2px outset BUTTONFACE;
        font:10 'ms sans serif';
        cursor:auto
    }
    .rowItem {
        border:8px solid #000000
    }
    .cellItem {
        font:10 'ms sans serif'
    }
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
var totalItems,absolutePosition,totalPages,currentPage;
var sortDir = "<%=order&orderColumn%>";
// Set the initial sort direction
var currentArrow = "arrow<%=orderColumn%>";
// Set the initial arrow to show

// startPage() handles the loading of the page 
// when the window.onload event fires.
function startPage() {
    tdcItems.sort = sortDir;
// Set the sort on the DSO.  We need to do the sorting 
//on the client so that all subsequent sorts 
//are consistent with the intial view of the page.
    tdcItems.Reset();// Perform the sort
    document.all.item("boundTable").dataSrc = "#tdcItems";
// Dynamically bind the table to the DSO<%
// Set the initial image and caption
    If order = "-" Then%>
    document.all.item(currentArrow).src = "images/down.gif";
    document.all.item(currentArrow).alt = "Sorted in descending order";<%
    Else%>
    document.all.item(currentArrow).src = "images/up.gif";
    document.all.item(currentArrow).alt = "Sorted in ascending order";<%
    End If%>
    document.all.item(currentArrow).style.visibility = "visible";// Make the arrow visible
    var oRecordSet = tdcItems.recordset;
// Create a client side recordset
    totalItems = oRecordSet.recordCount;
// Get the total number of items retreived
    pageCount();// Setup the page status
    if (totalItems != 0) {// Check for search results
        if (totalItems > <%=itemsPerPage%>) {
// Check to see if we need to use data paging
            document.all.item("boundTable").dataPageSize = <%=itemsPerPage%>;
// Use datapaging.  Set the page size.  
//Turn the recordset navigation on.
            for (i=0;i< document.all.item("recordSetButtons").length;i++) {
                document.all.item("recordSetButtons")(i).style.visibility = "visible";
            }
        }
        document.all.item("recordSpace").style.visibility = "visible";
// Turn the data on and turn the status off.
        document.all.item("pageSpace").style.visibility = "visible";
        document.all.item("holderTable").style.display = "none";
        document.all.item("boundTable").style.visibility = "visible";
    } else {
        document.all.item("waitMarquee").style.font = "bold 50 'courier new'";
// Tell the user that there are no records for the search 
//and give link for new search
        document.all.item("waitMarquee").innerHTML = "No records found.<BR></BR>Please 
<A HREF=\"search.asp?<%=Request.QueryString%>\" STYLE=\"text-decoration:underline!important\">search again</A>.";
    }
}

// The sortItem() function sorts the items in the column that has been
// clicked.  "itemName" is a reference to the ID of the column clicked.
function sortItem(itemName) {
    if (itemName.id != "HeaderNoHL") {
        currentArrow = "arrow"+itemName.id;
// Set the current arrow item.
        if (itemName.id == sortDir.substring(1,sortDir.length)) {
            if (sortDir.substring(0,1) == "-") {
// Reverse the sorting direction on the currently sorted column.
                sortDir = "+"+itemName.id;
            } else {
                sortDir = "-"+itemName.id;
            }
        } else {
            sortDir = "+"+itemName.id;
        }
        tdcItems.sort = sortDir;
// Set the sort for the DSO.
        if (sortDir.substring(0,1) == "+") {
// Change the arrow and it's text description.
            document.all.item(currentArrow).src = "images/up.gif";
            document.all.item(currentArrow).alt = "Sorted in ascending order";
        } else {
            document.all.item(currentArrow).src = "images/down.gif";
            document.all.item(currentArrow).alt = "Sorted in descending order";
        }
        for (i=0;i< document.all.tags("IMG").length;i++) {// Turn the arrows on and off 
					//depending on the sort column.
            if (document.all.tags("IMG")(i).id != "arrow"+itemName.id) {
                document.all.tags("IMG")(i).style.visibility = "hidden";
            } else {
                document.all.tags("IMG")(i).style.visibility = "visible";
            }
        }
        tdcItems.Reset();
// Reset the DSO. (This causes results to re-render)
        pageCount();
    } else {
        alert("You cannot sort by this column.");
    }
}

// The rollon() function handles the changing of colors and cursors 
// when the mouse goes over a header or record.  "itemName" is a 
// reference to the ID of the column clicked.
// If the tag is a TR then change the background color of the row to the
// background color of the menu.
// If the tag is a TH then change the cursor and highlighting (bordercolors)
// of the item.
function rollon(itemName) {
    if (itemName.tagName == "TR") {
        itemName.style.backgroundColor = "BUTTONFACE";
    } else if (itemName.tagName == "TH") {
        if ((window.event.toElement != null) && (window.event.fromElement != null)) {
            if ((window.event.fromElement.id != currentArrow) && (window.event.toElement.id != currentArrow)) {
                itemName.style.cursor = "hand";
                itemName.style.borderTopColor = "BUTTONHIGHLIGHT"
                itemName.style.borderLeftColor = "BUTTONHIGHLIGHT"
            }
        } else {
            itemName.style.cursor = "hand";
            itemName.style.borderTopColor = "BUTTONHIGHLIGHT"
            itemName.style.borderLeftColor = "BUTTONHIGHLIGHT"
        }
    }
    window.event.cancelBubble = true;
// Stop the event from bubbling up the hierarchy
}

// The rolloff() function handles the changing of colors and cursors
// when the mouse leaves a header or record.  "itemName" is a 
// reference to the ID of the column clicked.
// If the tag is a TR then change the background color of the row to the
// background color of the window.
function rolloff(itemName) {
    if (itemName.tagName == "TR") {
        itemName.style.backgroundColor = "WINDOW";
    } else if (itemName.tagName == "TH") {
        if ((window.event.toElement != null) && (window.event.fromElement != null)) {
            if ((window.event.toElement.id != currentArrow) && (window.event.fromElement.id != currentArrow)) {
                itemName.style.cursor = "auto";
                itemName.style.borderTopColor = "BUTTONFACE"
                itemName.style.borderLeftColor = "BUTTONFACE"
            }
        } else {
            itemName.style.cursor = "auto";
            itemName.style.borderTopColor = "BUTTONFACE"
            itemName.style.borderLeftColor = "BUTTONFACE"
        }
    }
    window.event.cancelBubble = true;
// Stop the event from bubbling up the hierarchy
}

// The mouseUp function handles the changing of the borders of 
// all TH tags back to normal after a mousedown event.
function mouseUp(itemName) {
    var coll = document.all.tags("TH");
    if (coll != null) {
        for (i=0; i< coll.length; i++) {
            if (coll[i].style.borderStyle != 'outset') {
                coll[i].style.borderStyle = 'outset';        
            }
        }
    }
}

// The pageCount() function handles the recordset navigation within a page.
// It also sets up and updates the navigation items in the 
//page as recordset navigation occurs.
function pageCount(direction) {
    switch (direction) {
        case "+":
            if (currentPage != totalPages) {
                boundTable.nextPage();
			// Navigate the recordset
                currentPage = currentPage + 1;
			// Set the current page
                absolutePosition = absolutePosition + <%=itemsPerPage%>;
// Set the absolute Position in the recordset
                if (currentPage != totalPages) {
// Set the recordnumber of the item at the end 
//of the currently displayed page
                    absolutePositionEnd = absolutePosition + 
<%=itemsPerPage-1%>;
                } else {
                    absolutePositionEnd = totalItems;
                }
            } else {
                alert("You are already on the last page.");
            }
            break;
        case "++":
            if (currentPage != totalPages) {
                for (i=currentPage;i<=totalPages;i++) {
                    boundTable.nextPage();
                }
                absolutePosition = ((totalPages - currentPage) * <%=itemsPerPage%>) + absolutePosition;
                currentPage = totalPages;
                absolutePositionEnd = totalItems;
            } else {
                alert("You are already on the last page.");
            }
            break;
        case "-":
            if (currentPage != 1) {
                boundTable.previousPage();
                currentPage = currentPage - 1;
                absolutePosition = absolutePosition - <%=itemsPerPage%>;
                absolutePositionEnd = absolutePosition + <%=itemsPerPage-1%>;
            } else {
                alert("You are already on the first page.");
            }
            break;
        case "--":
            if (currentPage != 1) {
                for (i=currentPage;i>=1;i--) {
                    boundTable.previousPage();
                }
                absolutePosition = 1
                currentPage = 1;
                absolutePositionEnd = absolutePosition + <%=itemsPerPage-1%>;;
            } else {
                alert("You are already on the first page.");
            }
            break;
        default:
            totalPages = Math.ceil(totalItems / <%=itemsPerPage%>);
// Figure out how many pages exist (based on the items per page and total items found
            absolutePosition = 1;// Set the initial position.
            currentPage = 1;// Set the initial page
            if (totalItems > <%=itemsPerPage%>) {
// Set the recordnumber of the item at the end of the currently displayed page
                absolutePositionEnd = absolutePosition + <%=itemsPerPage-1%>;
            } else {
                absolutePositionEnd = totalItems;
            }
            document.all.item("totalRecordsSpace").innerHTML = "<B>"+totalItems+"</B> total items found.\n";
// Fill in the total number of items returned
    }
    document.all.item("recordSpace").innerHTML = "Items <B>"+absolutePosition+"</B> through <B>"+absolutePositionEnd+"</B> shown.\n";
// Fill in the current page and current positions in the recordset
    document.all.item("pageSpace").innerHTML =  "Page <B>"+currentPage+"</B> of <B>"+totalPages+"</B>.\n";
}
</SCRIPT>
</HEAD>
<BODY TOPMARGIN="0" LEFTMARGIN="0" onload="startPage()">
<TABLE ID="holderTable" WIDTH=100%>
<TR>
    <TD ALIGN="CENTER" ID="waitMarquee">&#160;<MARQUEE STYLE="font:bold 50 'courier new'">Searching</MARQUEE>&#160;</TD>
</TR>
</TABLE>
<TABLE COLS="<%=tableColumns%>" BORDER="0" CELLSPACING="0" 
WIDTH="100%" ID="boundTable" STYLE="visibility:hidden" 
onmouseup="mouseUp()">
<THEAD>
<TR BGCOLOR="#000000">
    <TD COLSPAN="<%=tableColumns-2%>">
        <TABLE CELLSPACING="0" CELLPADDING=0 WIDTH=100% BORDER="0">
            <TR>
                <TD ALIGN="CENTER" ID="titleSpace" 
		STYLE="font:bold 50 'courier new';
		color:#FFFFFF"><NOBR>Search Results</NOBR></TD>
            </TR>
        </TABLE>
    </TD>
<!--
This cell holds the page information and recordset navigation.
Visibility depends on the search parameters and results.
-->
    <TD COLSPAN="<%=tableColumns-3%>">
        <TABLE CELLSPACING="0" CELLPADDING=0 WIDTH=100% BORDER="0">
            <TR>
                <TD ALIGN="CENTER" NOWRAP ID="totalRecordsSpace" 
			COLSPAN="4" STYLE="font:10 'ms sans serif';
			color:#FFFFFF"></TD>
            </TR>
            <TR>
                <TD ALIGN="CENTER" NOWRAP ID="recordSpace" 
			COLSPAN="4" STYLE="visibility:hidden;font:10 'ms sans serif';
			color:#FFFFFF"></TD>
            </TR>
            <TR>
                <TD ALIGN="CENTER" NOWRAP ID="pageSpace" 
			COLSPAN="4" STYLE="visibility:hidden;font:10 'ms sans serif';
			color:#FFFFFF"></TD>
            </TR>
<!--
This row handles the navigation through the recordset.
There is an identical row at the bottom of the page in case the end user scrolls these buttons off the top of the page.
-->
            <TR ID="recordSetButtons" STYLE="visibility:hidden" 
			onmousedown="window.event.srcElement.style.borderStyle='inset'" 
			onmouseover="rollon(window.event.srcElement)" 
			onmouseout="rolloff(window.event.srcElement)">
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('--')" 
			TITLE="Click here to go to the first page of data">&lt;&lt;</TH>
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('-')" 
			TITLE="Click here to go to the prevous page of data">&lt;</TH>
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('+')" 
			TITLE="Click here to go to the next page of data">&gt;</TH>
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('++')" 
			TITLE="Click here to go to the last page of data">&gt;&gt;</TH>
            </TR>
        </TABLE>
    </TD>
</TR>
<!--
Create the dataspace.  Handle clicking on items within the space as well as mouse movement.
-->
<TR onclick="sortItem(window.event.srcElement)" 
	onmousedown="window.event.srcElement.style.borderStyle = 'inset'" 
	onmouseover="rollon(window.event.srcElement)" 
	onmouseout="rolloff(window.event.srcElement)">
<!--
Create table headers for each column.  Clicking on a header will cause
a sort for sortable columns.  The cursor will change on mouseover and
mouseout events.  Image arrows will change depending on sort directions.
-->
    <TH ALIGN="LEFT" NOWRAP 
	CLASS="menuItem" ID="Subject" 
	TITLE="Click here to sort by Subject">Subject&#160;&#160;<
	IMG ID="arrowSubject" SRC="images/up.gif" 
	WIDTH="10" HEIGHT="10" 
	STYLE="visibility:hidden">&#160;&#160;</TH>
    <TH ALIGN="LEFT" WIDTH="40%" NOWRAP 
	CLASS="menuItem" ID="Title" 
	TITLE="Click here to sort by Title">Title&#160;&#160;<
	IMG ID="arrowTitle" SRC="images/up.gif" 
	WIDTH="10" HEIGHT="10" 
	STYLE="visibility:hidden">&#160;&#160;</TH>
    <TH ALIGN="LEFT" WIDTH="25%" NOWRAP 
	CLASS="menuItem" ID="LastName" 
	TITLE="Click here to sort by Author">Author&#160;&#160;<
	IMG ID="arrowLastName" SRC="images/up.gif" 
	WIDTH="10" HEIGHT="10" 
	STYLE="visibility:hidden">&#160;&#160;</TH>
    <TH ALIGN="LEFT" NOWRAP 
	CLASS="menuItem" ID="Price" 
	TITLE="Click here to sort by Price">Price&#160;&#160;<
	IMG ID="arrowPrice" SRC="images/up.gif" 
	WIDTH="10" HEIGHT="10" 
	STYLE="visibility:hidden">&#160;&#160;</TH>
    <TH ALIGN="LEFT" NOWRAP 
	CLASS="menuItem" ID="HeaderNoHL" 
	TITLE="You cannot sort this column">More info.&#160;</TH>
</TR>
</THEAD>
<TBODY>
<!--
Handle the rollover of the rows (this is basically current record highlighting)
with rollon and rolloff functions.
-->
<TR CLASS="rowItem" 
	onmouseover="rollon(this)" 
	onmouseout="rolloff(this)">
    <TD ALIGN="LEFT" CLASS="cellItem">
	<SPAN DATAFLD="Subject"></SPAN></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
	<SPAN DATAFLD="Title" DATAFORMATAS="HTML">
	</SPAN></TD>
    <TD ALIGN="LEFT" CLASS="cellItem">
	<SPAN DATAFLD="LastName"></SPAN>, 
	<SPAN DATAFLD="FirstName"></SPAN></TD>
    <TD ALIGN="RIGHT" CLASS="cellItem">
	<SPAN DATAFLD="PriceDisplay"></SPAN></TD>
    <TD ALIGN="CENTER" NOWRAP CLASS="cellItem">
	<A DATAFLD="ViewDocUrl">more info...</A></TD>
</TR>
</TBODY>
<TFOOT>
<TR>
    <TD ALIGN="CENTER" COLSPAN="<%=tableColumns-2%>" 
	STYLE="font:14 'ms sans serif'"><B>
	<A HREF="search.asp?<%=Request.QueryString%>" 
	STYLE="text-decoration:underline!important">search again</A></B></TD>
    <TD COLSPAN="<%=tableColumns-3%>">
        <TABLE CELLSPACING="0" CELLPADDING=0 WIDTH=100% BORDER="0">
            <TR ID="recordSetButtons" STYLE="visibility:hidden" 
		onmousedown="window.event.srcElement.style.borderStyle = 'inset'" 
		onmouseover="rollon(window.event.srcElement)" 
		onmouseout="rolloff(window.event.srcElement)">
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('--')" 
			TITLE="Click here to go to the first page of data">&lt;&lt;</TH>
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('-')" 
			TITLE="Click here to go to the prevous page of data">
&lt;</TH>
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('+')" 
			TITLE="Click here to go to the next page of data">&gt;</TH>
                <TH ALIGN="CENTER" VALIGN="MIDDLE" 
			CLASS="menuItem" onclick="pageCount('++')" 
			TITLE="Click here to go to the last page of data">&gt;&gt;</TH>
            </TR>
        </TABLE>
    </TD>
</TR>
</TFOOT>
</TABLE>
</BODY>
</HTML><%
Else 'Send client back to the start
    Response.Redirect Left(Request.ServerVariables("PATH_INFO"),InStrRev(Request.ServerVariables("PATH_INFO"),"/"))
End If%>

Figure 13   startPage

function startPage() {
    tdcItems.sort = "+subject";
    tdcItems.Reset();
    document.all.item("boundTable").dataSrc = "#tdcItems";
    document.all.item("subjectArrow").src = "images/up.gif";
    document.all.item("subjectArrow").alt = "Sorted in ascending order";
    document.all.item("subjectArrow").style.visibility = "visible";
    var oRecordSet = tdcItems.recordset;
    totalItems = oRecordSet.recordCount;
    document.all.item("recordSpace").style.visibility = "visible";
    document.all.item("boundTable").style.visibility = "visible";
}

Figure 14   sortItem

function sortItem(itemName) {
    if (itemName.id != "HeaderNoHL") {
        currentArrow = "arrow"+itemName.id;
        if (itemName.id == sortDir.substring(1,sortDir.length)) {
            if (sortDir.substring(0,1) == "-") {
                sortDir = "+"+itemName.id;
            } else {
                sortDir = "-"+itemName.id;
            }
        } else {
            sortDir = "+"+itemName.id;
        }
        tdcItems.sort = sortDir;
        if (sortDir.substring(0,1) == "+") {
            document.all.item(currentArrow).src = "images/up.gif";
            document.all.item(currentArrow).alt = "Sorted in ascending order";
        } else {
            document.all.item(currentArrow).src = "images/down.gif";
            document.all.item(currentArrow).alt = "Sorted in descending order";
        }
        for (i=0;i< document.all.tags("IMG").length;i++) {
            if (document.all.tags("IMG")(i).id != "arrow"+itemName.id) {
                document.all.tags("IMG")(i).style.visibility = "hidden";
            } else {
                document.all.tags("IMG")(i).style.visibility = "visible";
            }
        }
        tdcItems.Reset();
    } else {
        alert("You cannot sort by this column.");
    }
}