# tblDocEx

glbBody:
showcategories.cfm

This page retrieves the CategoryID, CategoryName, and CategoryDesc
fields from the StoreCategories data table and uses the resulting query
to build an HTML table.

Here is the code to get the categories:

{CODE} <CFQUERY DATASOURCE="CFexamples40" NAME="GetCategories">
    SELECT * FROM StoreCategories
</CFQUERY> {/CODE}

The information for each category is displayed within a <CFOUTPUT>
block, where the category name and description outputted. Also, a form is
created for each category, and a hidden form element that contains the
category's ID number; this ID number gets passed when the Browse button
is pressed.

This code is shown below, with HTML table formatting tags removed:

{CODE} <CFOUTPUT QUERY="GetCategories">
#CategoryName#
#CategoryDesc#
</CFOUTPUT> {/CODE}


glbBody:
showitems.cfm

This page displays the items in a particular category. The category is determined 
    by the variable #CategoryID#, which can be either a Form or URL type variable.

First, we want to display the name of the category we're browsing. Since we 
    only have the CategoryID, we need to do a query to retrieve the actual name.

{CODE} <CFQUERY DATASOURCE="CFexamples40" NAME="GetCurrentCategory">
    SELECT CategoryName FROM StoreCategories
    WHERE CategoryID = #CategoryID#
</CFQUERY> {/CODE}
Now we do a query to retrieve the actual items that belong to the category. 
    The StoreItems table contains the part number, item name, description, and 
    price, but the manufacturer name is stored in a separate table, so we need 
    to do a simple join.

{CODE} <CFQUERY DATASOURCE="CFexamples40" NAME="GetItems">
    SELECT StoreItems.*, StoreManufacturers.Name
    FROM StoreItems, StoreManufacturers
    WHERE StoreItems.ManufacturerID = StoreManufacturers.ManufacturerID
        AND CategoryID = #CategoryID#
</CFQUERY> {/CODE}
Now we just do a simple CFOUTPUT. The FORM is submitted if the item is to be 
    added to the cart.

{CODE} <CFOUTPUT QUERY="GetItems">
#ItemName#
#DollarFormat(ItemPrice)#
#ItemDesc#
Manufacturer: #Name#
Part Number: #PartNum#
</CFOUTPUT> {/CODE}


glbBody:
additem.cfm

This template adds an item (indicated by Form.ItemID) to the shopping
cart, then uses _showitems.cfm to display the contents of the cart and
allow the user to change quantities.

If the item already exists in the shopping cart, the template simply adds
one to the quantity listed for that item. If the item does not exist,
it is appended to the end of the shopping cart and the quantity set to 1.

{CODE}
<CFIF ListFind(Session.StoreItems, Form.ItemID) NEQ 0>

    <CFSET ItemPosition = ListFind(Session.StoreItems, Form.ItemID)>
    <CFSET CurrentQuantity = ListGetAt(Session.StoreQuantities, ItemPosition)>
    <CFSET Session.StoreQuantities = ListSetAt(Session.StoreQuantities, ItemPosition, CurrentQuantity + 1)>

<CFELSE>

    <CFSET Session.StoreItems = ListAppend(Session.StoreItems, Form.ItemID)>
    <CFSET Session.StoreQuantities = ListAppend(Session.StoreQuantities, 1)>

</CFIF> {/CODE}

Then, a CFQUERY is performed to get the name of the item that was just
added to the cart (since only the ItemID is passed to this template).  Finally,
a JavaScript alert box notifies the user that the item was added, and the
file _showitems.cfm is CFINCLUDE-ed to display the contents of the cart and
allow the user to change item quantities.

Related topics

Shopping Cart Concepts

Changing Quantities


glbBody:
changequants.cfm

This template is called by the form in _showitems.cfm. (_showitems.cfm 
is never called by the browser, but is CFINCLUDE-ed by additems.cfm, changequants.cfm,
and viewcart.cfm.) It takes several form variables as input, adjusts the
quantities of the items in the shopping cart, and then redisplays the
shopping cart by CFINCLUDE-ing _showitems.cfm.

The first form variables used by the template are Form.StoreItems and
Form.StoreQuantities. These are used to ensure the integrity of the shopping
cart. If the user is using several different browser windows, it is possible
that the state of the shopping cart has changed since the calling form was 
rendered. If that is the case, changequants.cfm will have unpredictable results;
therefore, _showitems.cfm embeds the state of the shopping cart into the form
(through fields of type Hidden) and changequants.cfm uses these hidden fields to
restore the shopping cart to the previous state.

Here is code in _showitems.cfm which produces the hidden form fields...

{CODE} <CFOUTPUT>
</CFOUTPUT> {/CODE}

...and this is the code in changequants.cfm which restores the shopping cart.

{CODE} <CFSET Session.StoreItems = Form.StoreItems>
<CFSET Session.StoreQuantities = Form.StoreQuantities> {/CODE}

Now that we are sure that the shopping cart is in proper order, we can go
about actually changing the quantities of the items. The item quantities
are stored in text fields with names that indicate the item they represent. 
For example, if Form.ItemID1 = "5", then the quantity of Item 1 in the shopping
cart should be set to 5.

{CODE} <CFLOOP INDEX="CurrVal" FROM="1" TO="#ListLen(Session.StoreItems)#">
    <CFSET NewQuantity = Evaluate("Form.Item" & ListGetAt(Session.StoreItems, CurrVal))>
    <CFSET Session.StoreQuantities = ListSetAt(Session.StoreQuantities, CurrVal, Trim(NewQuantity))>
</CFLOOP> {/CODE}

Finally, _showitems.cfm is CFINCLUDE-ed to allow the user to view the
cart contents, make further changes to quantities, or check out.


glbBody:
_showitems.cfm

This template shows a detailed view of the shopping cart and allows users
to change quantities of items or "check out". Note: This template is
only intended to be executed via CFINCLUDE from other templates, and not to
be called on its own (hence the "_" preceding the name).

First, we want to make sure that using the Back button on the browser can
never present an old shopping cart to the user. So we insert the following two
lines of code:

{CODE} <CFHEADER Name="Expires" Value="#Now()#">
<CFHEADER NAME="pragma" VALUE="no-cache"> {/CODE}

The first tag will make POST pages display "data missing, please press reload"
and the second will (hopefully) make other pages not enter the cache.

Now we want to loop through the shopping cart and delete all items that have a quantity of 0 (or less).

{CODE} <CFSET LoopVar = 1>
<CFLOOP CONDITION="LoopVar LTE ListLen(Session.StoreItems)">
        <CFIF ListGetAt(Session.StoreQuantities, LoopVar) LT 1>
                <CFSET Session.StoreQuantities = ListDeleteAt(Session.StoreQuantities, LoopVar)>
                <CFSET Session.StoreItems = ListDeleteAt(Session.StoreItems, LoopVar)>
        <CFELSE>
                <CFSET LoopVar = LoopVar + 1>
        </CFIF>
</CFLOOP> {/CODE}

(Normally, we could simply CFLOOP through the list, but since we have
two lists to deal with (StoreItems and StoreQuantities), we use an
independent variable--LoopVar--instead.)

Next we just display some column headings...

{CODE}
Item #
Description
Unit Price
Quantity
Subtotal
{/CODE}

If there are no items in the shopping cart (Session.ShowItems is ""),
this template is pretty much through. Otherwise, we lay out the rest of the
table that will display the contents of the shopping cart and allow quantity changes
to be made. We start by opening a form:

{CODE}
<CFOUTPUT>
</CFOUTPUT> {/CODE}

The hidden fields are to ensure the integrity of the shopping cart.
In other words, if the browser goes off and does some more shopping, then
tries to use this out-of-date shopping cart to change quantities, the
out-of-date shopping cart will overwrite the new one before quantity changes
are made.

The inline comments below pretty well explain the rest of the template...

{CODE}
<CFSET TotalCost = 0>

<CFLOOP LIST="#Session.StoreItems#" INDEX="CurrentItemID">
        
        <CFSET ItemPosition = ListFind(Session.StoreItems, CurrentItemID)>
        <CFSET Quantity = ListGetAt(Session.StoreQuantities, ItemPosition)>

        <!--- This query is just to get the name and price of the current
            item so that we can display that data in the table --->
        <CFQUERY DATASOURCE="CFexamples" NAME="GetCurrentItem">
                SELECT ItemID, PartNum, ItemName, ItemPrice FROM StoreItems
                WHERE ItemID = #CurrentItemID#
        </CFQUERY>

        <CFOUTPUT QUERY="GetCurrentItem">
#PartNum#
#ItemName#
#DollarFormat(ItemPrice)#
                        #DollarFormat(ItemPrice * Variables.Quantity)#
        </CFOUTPUT>

        <CFSET TotalCost = TotalCost + GetCurrentItem.ItemPrice * Variables.Quantity>

</CFLOOP>

                Total
                <CFOUTPUT>#DollarFormat(TotalCost)#</CFOUTPUT>
{/CODE}


glbBody:
Shopping Cart Concepts

The shopping cart consists of a pair of Session variables:
StoreItems and StoreQuantities.

Session.StoreItems is a list of the items that exist in the
cart (or more specifically, a list of ItemID's). For example, if
Session.StoreItems = "1,3,4,9" then the items in the database table
StoreItems with ItemID's 1, 3, 4, and 9 exist in the shopping cart.

Session.StoreQuantities is a list of quantities that corresponds
with the list of items that is Session.StoreItems. For example, if the
Session.StoreItems used in the previous example had a corresponding
Session.StoreQuantities = "3,2,4,5", then the shopping cart would
contain three of item 1, two of item 3, four of item 4,
and five of item 9.

Note that the shopping cart is only valid if StoreItems and
StoreQuantities contain the same number of list elements. Furthermore,
Session.StoreItems should never contain anything but valid ItemID's and
StoreQuantities should never contain anything other than positive integers.

Related topics

Session Variables


glbBody:
viewcart.cfm

This page simply displays the current shopping cart by CFINCLUDE-ing _showitems.cfm.


{CODE} <CFINCLUDE TEMPLATE="_showitems.cfm"> {/CODE}


glbBody:
checkout.cfm

This page displays a form that gets the user's information for order
processing. Notice that it uses <CFFORM> and <CFINPUT> instead
of <FORM> and <INPUT>; that is because the CF-enhanced elements
allow you to do data validation automatically.  For example:


{CODE} <CFFORM ACTION="orderconfirm.cfm"
METHOD="POST">
    <CFINPUT TYPE="Text" NAME="FirstName"
MESSAGE="Please enter your name!" REQUIRED="Yes"
SIZE="15">
    <CFINPUT TYPE="Text" NAME="Zip"
MESSAGE="Please enter your zipcode!" VALIDATE="zipcode"
REQUIRED="Yes" SIZE="10">
</CFFORM> {/CODE}

In this example, the form will produce a JavaScript alert when submitted
if either the FirstName or Zip fields are left blank, or if the Zip field is
not a valid zip code.


# tblPbCnt

glbData:
To learn more about new features in Allaire ColdFusion 4.5, check out the new features page.


glbData:
Extremely fast patented AeroBolt design, in sizes 3.2 to 6.4 metres. Integrated Zylar panels feature loose luff pattern and flat profile. Includes high-stress carbon-fibre mast, PoleSok ballistic nylon sleeve and indestructible nylon mast bushing, guaranteed for 5 years.


glbData:
Arguably the most advanced sail available for all-out racing and performance sailing. See the store for more information and pricing.2


glbData:
Vela windsurf resorts in Aruba, Baja, Cbarete, Margarita, Coche, and Maui.
Maui


glbData:
Determines if a file is a valid GIF or JPEG, and if so, returns its height, width and compression type.


# tblPbCTp

strTypDesc:
This content type is used to hold any ASCII data or HTML


strTypDesc:
Any binary file attachments to be downloaded by the user


strTypDesc:
A short (1-paragraph) blurb summarizing the content


# tblStCat

glbCatDesc:
Precise dynamics and the latest designs in windsurfing sails. Everything from performance sails, tuned for wave leaping action, to more forgiving models better suited to light wind and quiet riding.


glbCatDesc:
Carbon fibre masts for max performance. Protect yourself at sea with the most advanced 100% carbon fibre masts available. Venture into the open ocean without worrying about snapping off your ride home.


glbCatDesc:
Performance boards for hardcore conditions. Designed for speed and comfort. Check out our neoprene DogSnuggler foot straps!


# tblStItm

glbItmDesc:
Extremely fast patented AeroBolt design, in sizes 3.2 to 6.4 metres. Integrated Zylar panels feature loose luff pattern and flat profile. Includes high-stress carbon-fibre mast, PoleSok ballistic nylon sleeve and indestructible nylon mast bushing, guaranteed for 5 years.

strTeaser:
Extremely fast patented AeroBolt design.


glbItmDesc:
A more versatile sail for the non-competitive performance sailer. The perfect match of performance and handling ease. Sizes 5.2 to 7.8 metres. Ranks highest in handling and planing characteristics for any sail in this price range. Includes hardened glass patented BondoMast technology, PoleSok ballistic sleeve, and hardcore nylon mast bushing, guaranteed for 5 years.

strTeaser:
A more versatile sail for the non-competitive performance sailer.


glbItmDesc:
The MondoSlab, with enhanced waveform sidecut technology, gives practically excessive performance in both on-shore and side-shore situations. Length: 314.5cm, width: 60.25cm. Especially effective in light wind. Weight; 9.5 lbs. Ideal sail: 5.0 - 8.0. Includes patented DogSnuggler neoprene foot straps for those moonlight runs to Nantucket and back.

strTeaser:
Enhanced waveform sidecut technology, gives practically excessive performance in both on-shore and side-shore situations.


glbItmDesc:
Derived from the technology behind super strength-to-weight space station construction technology, the RipperStik combines tremendous strength with light weight and perfrect flex characteristics. Available in 415, 425, 440, and 480cm lengths. Weight, under 2.6g. Slip this baby into our patented PoleSok and ride.

strTeaser:
Combines tremendous strength with light weight and perfrect flex characteristics.


glbItmDesc:
Extremely fast patented Mistral design, in sizes 3.4 to 7.4 metres. Integrated Zylar panels feature loose luff pattern and flat profile. Includes high-stress carbon-fibre mast, PoleSok ballistic nylon sleeve and indestructible nylon mast bushing, guaranteed for 8 years.


glbItmDesc:
This sail has competitive performance all over it. The perfect match of performance and handling ease. Sizes 6.2 to 7.8 square metres. Popular among beginners  in this price range. Basicy eurothane construction, guaranteed for 3 years.

strTeaser:
The perfect match of performance and handling ease.


glbItmDesc:
The No Fear, with its lightweight, polymer construction is some of the most state of the art board technology available. Performance in low wind is poor, but anything above a breeze and sharks have reason to fear. Length: 290.5cm, width: 58.25cm. Especially effective in heavy wind. Weight; 5.5 lbs. Ideal sail: 9.0 - 11.0. Worth every penny of difference over the MondoSlab.

strTeaser:
Some of the most state of the art board technology available.


glbItmDesc:
A better weight-strength ratio cannot be found. Combines tremendous strength with light weight and perfrect flex characteristics. Available in 425, 430, 440, and 490cm lengths. Weight, under 2 kg. Ideal for the RocketBoard.

strTeaser:
A better weight-strength ratio cannot be found.


