The CategoryList Include File
The first thing our ASP code does is create an ADODB Recordset to obtain a list
of categories from the database. We use the ASP Server object's CreateObject
method to create a new ADODB.Recordset object. The Recordset's Open method fetches
the data we need by executing the ListCategories stored procedure we created
earlier. sdbConnString is a global variable defined outside of the include file,
in another server-side include file that is inserted into every ASP page in the
web site, but we will come to this in good time.
<% // Number of table cells per row var iNoPerRow = 4; var loRS; var scategoryDesc; // Create ADODB.Recordset object then execute of ListCatgeories // stored procedure loRS = Server.CreateObject("ADODB.Recordset"); loRS.Open("Exec ListCategories", sdbConnString); %>
Next we have the starting tags of our HTML table. The ASP code following is the start of our while loop which loops though the recordset rows and creates our table's rows and cells:
<TABLE> <TR> <% // Loop though the returned recordset // populating table cells/links while (!(loRS.Eof)) { scategoryDesc = loRS("Description"); %>
HTML with embedded ASP script comes next. Here we write the HTML of the table cell, inserting the hyperlink which the user will click to view goods within that music category. We append the CatId and Category Description to the end of the hyperlink's URL. The ASP page which this link navigates to can pick up the data from the ASP Request object's QueryString collection. Note that Description has been coded with the escape method to ensure no confusion occurs when it is passed as part of a URL. Characters such as the ampersand (&) are converted into their ASCII value so they are not confused with an ampersand which indicates another item of data in the URL.
<TD WIDTH="150" height="50"> <FONT SIZE=5 COLOR=#FF8040 FACE="Comic Sans MS"> <STRONG> <A HREF="Browse.asp?CatId=<%=loRS("CatId")%> &Description=<%=escape(scategoryDesc)%> &StartItemId=-1"> <%=loRS("Description")%> </A> </STRONG></FONT> </TD>
Finally we come to the end of the while loop and table:
<% // Decrement row counter - if hit our limit for the row // start a new row iNoPerRow--; if (iNoPerRow == 0) { Response.Write("</TR><TR>"); iNoPerRow = 4; } loRS.MoveNext(); } // end of while loop loRS.Close(); loRS = null; %> </TABLE>
Save the include file as CategoryList.inc into the MusicMad
directory you created earlier. The .inc extension is not compulsory for include
files but it is the one recommended by Microsoft.
The Global Include File
Our next task is to create another include file which will be added at the start
of all our ASP pages using the include directive. It contains a number of global
constants and general functions.
At the very top of the file on a separate line by itself is an ASP preprocessing
directive. This must be the first line and it must be separate from other ASP
code or the page will fail. There are a number of ASP preprocessing directives,
some of which we will come to later, but this particular one sets the default
language for all ASP on this page to JScript:
<%@ Language="JScript"%>
Next a couple of global constants used in the web site are
declared. The sdbConnString is our connection string we use in our ADO statements
to connect to the database. I have used a DSN-less connection for ease of set
up (there is no set up needed!). If you prefer, you can set up an ODBC data source
which does make it easier to change data sources without changing any code. Even
if you never change your database you may change its location to another server,
something you can easily do with an ODBC data source.
Most of the database connection string is self-explanatory. However some needs
further explanation. The Provider is our database, here SQL Server 7. Initial
Catalog is our database. In Data Source we have used a period (full stop). This
is an alias for the local server, similar to using localhost for the local web
server. If you find this does not work, for example if your SQL Server database
is not installed or you are using a Win95/98 machine, then replace the period
with the name of the SQL Server your database is installed on.
Response.Buffer = true buffers the sending of page content and has been used
to allow us to change cookie values once the HTTP header has been written. When
the response is buffered, the result of the ASP code (HTML and client-side script)
is stored in the server's memory until either the end of the page is reached
or a Response.Flush or Response.End methods are called. Buffering also means
that we can change a cookie in server-side ASP code even after the <HTML>
tag, something otherwise disallowed.
<% // Global Constants Response.Buffer = true; // DSN-less Connection String to database var sdbConnString = "Provider=SQLOLEDB.1; Password=madforit; Persist Security Info=True; User ID=MMCustomer; Initial Catalog=MusicMad; Data Source=."; // Number of goods per page to display var lMaxPerPage = 15;
Next we come to the code for the first of the two functions included with the include file. This is part of our web site's shopping basket functionality. It extracts cookie data for a particular stock item contained within the basket – the ItemId, which is the same as that defined in the database, is used for identifying items. Data held within the cookie for a particular item includes ItemId, Qty, ArtistName, Item Description and the Price of an individual item. It is contained in a single string which uses & to delimit data within an item and the £ to indicate the end of the item's data.
function getItemFromCookie(lItemId, sCookie) { // Find Item start and end var lStart = sCookie.indexOf(lItemId + "&"); var lEnd = sCookie.indexOf("£",lStart + 1); // put that into a new string - excluding £ at end var sItem = sCookie.slice(lStart,--lEnd); var ItemData = sItem.split("&"); return ItemData }
The getItemFromCookie functions counterpart is the setItemToCookie
function. Its parameters are ItemData, an array containing ItemId, ArtistName,
item Description and Price, and the current value of the basket cookie.
There are three situations the routine deals with:
- The item already exists in the basket in which case we need to update its quantity.
- If the updated quantity is zero then the item needs to be deleted from the basket, otherwise we override the existing value.
- If the item is not already in the basket then we need to concatenate it to the end of the basket cookie string.
Regular Expressions, a powerful feature of JavaScript versions 1.2 and above, and the string object's replace method are used to update an existing quantity. For example, if we had an ItemId of 12, with a current Qty of 2, ArtistName "REM", Description "Monster" and Price of 9.99 then the cookie for that item will look like:
ID12&2&REM&Monster&9.99£&
Our regular expression created by the line new RegExp(lItemId + "&[0-9]+"), will be:
ID12&[0-9]+
This will match any occurrences of ID12& and any number of digits (which make up the quantity). [0-9] indicates any character in the range 0 - 9 (i.e. any digit). The + indicates that one or more of the previous character, i.e. a digit, must follow.
function setItemToCookie(ItemData, sCookie) { // ItemData is array with elements // ItemId,Qty,ArtistName,Title,Price var sBasketCookie = new String(sCookie); var lItemId = new String(ItemData[0]); // Is that item already in the basket var lItemStart = sBasketCookie.indexOf(lItemId + "&") // update qty of existing Item if (lItemStart >= 0) { // If new VALUE is not 0 then update Qty if (ItemData[1] > 0) { var SearchPattern = new RegExp(lItemId + "&[0-9]+"); sBasketCookie = sBasketCookie.replace(SearchPattern,lItemId + _ "&" + ItemData[1]); } else { // new Item Qty is 0 so remove it from basket var lItemEnd = sBasketCookie.indexOf("£&",lItemStart + 1) + 2; sBasketCookie = sBasketCookie.replace _ (sBasketCookie.slice(lItemStart,lItemEnd),""); } } else { // Item not in basket already - so add it sBasketCookie = sBasketCookie.concat(lItemId + "&",ItemData[1] + _ "&",ItemData[2] + "&",ItemData[3] + _ "&",ItemData[4] + "&"); } return sBasketCookie; } %>
Save this page as ServerSideGlobalDef.inc.
Comments