HZML Loops

One tool in the box of Hazel's Markup Language which merits special attention is an "Loop". A Hazel-Loop element contains text which is rendered multiple times for each of a given set of elements. There are two basic types of loops, described below.

Product Loops

In the beginning there was the "selected" loop. It was devised to enable a catalog designer to display the list of products selected by the shopper in any conceivable format. Within the opening <Hazel-Loop> and the closing </Hazel-Loop> tags, text was inserted which would be repeated for each item in the shopper's cart. Within the loop body, %HZI tokens are replaced with information for the particular product over which Hazel was currently looping.

The "selected" loop is a specific type of "products" loop. A products loop can loop over more than just the items the shopper selected. It can also show all items of a particular group, SKUID you have explicitly specified, items matching a user search, or items matching any search query you specify.

Before going into each specific type of products loop, here are the attributes common to all of them:

<Hazel-Loop> ... </Hazel-Loop>

Type=string

One of selected, matches, products, query, optioned and pickups.

Sort=[+-]fieldname

Common to all product loops. The name of a product field on which you would like to sort the products being looped. Default order is ascending (lowest to highest); to reverse the sort order, insert a minus-sign before the fieldname.

Min=number

Common to all product loops. The minimum number of loops you want to be performed. If there are less products available to loop than this minimum, further loops will be performed with a null product context (%HZI tokens return nothing.)

Max=number

Common to all product loops. The maximum number of loops you want to be performed. Stop at this many iterations even if there are more products waiting to be looped.

Size=number[%]

Common to all product loops. The number of loops you wish to be performed, chosen at random. If a percentage, show that percentage of the total population of products which would have been displayed.

The current loop number can be accessed within the loop body with %HZH_PRODUCT_LOOP_COUNT. After the loop, you can use %HZH_PRODUCT_LOOP_TOTAL to find out the total number of iterations which occurred.

<Hazel-Loop Type="Products" Src="FOO;BAR;BAZ">
%HZI_NAME will be one of the names of SKUID FOO, BAR, or BAZ.
</Hazel-Loop>

<Hazel-Loop Type="Products" Src="FOO;BAR;BAZ" Max=2>
%HZI_NAME will be one of the names of SKUID FOO, BAR.  We
skip BAZ because we specified a maximum loop count of 2..
</Hazel-Loop>

<Hazel-Loop Type="Products" Src="FOO;BAR;BAZ" Sort="SKUID">
%HZI_NAME will be one of the names of SKUID BAR, BAZ, and FOO -- and in
that order since we specified a sort on SKUID.
</Hazel-Loop>

Each products loop basically works like the next one. You get the body of the loop repeated for each product over which you're looping. There are some special attributes (and sometimes extra available %HZI tokens) available for each particular type of product loop, which we'll go over below.

<Hazel-Loop> ... </Hazel-Loop>

Type=SELECTED

The original loop. No extra attributes beyond those common to all product loops, shown above. The products looped over are those selected by the shopper for purchase.

Examples of the selected loop can be found throughout your standard templates, particularly "view" and "checkout".

<Hazel-Loop> ... </Hazel-Loop>

Type=PICKUPS

Similiar in content to the selected loop, the pickups loop is available only at the final finish stage of a softgoods order, iterating over selected items which have downloadable pickups available.

In addition to the standard %HZI tokens, each product in a pickups loop will have an %HZI_PICKUP_ID token available. This token is used as the item of a "pickup" action to initiate a product download.

<Hazel-True Token="%HZH_SOFTGOODS_REGISTERED">
The "softgoods" you've ordered can be downloaded from the URL listed below. 
 They will be available until approximately one hour from now.

<Hazel-Loop Type="Pickups">
* %HZI_NAME: %HZU_MAIN_NONSECURE?action=pickup&item=%HZI_PICKUP_ID
</Hazel-Loop>

</Hazel-True>

<Hazel-Loop> ... </Hazel-Loop>

Type=MATCHES

This type of loop can only be used in a search/matches.html template. The products over which it loops are a single "page" of match results from Hazel's search engine. To loop over items matches a search query you specify, use the query loop instead.

The sole occurence of the matches loop is in the hazel-cat/templates/search/matches.html template. It's a pretty standard products loop with no extra attributes. The only quirk to keep in mind is that it will loop over different products each time, each one a set of products of a certain "page" of matches. Paging between such sets is handled for you--see the matches template!

<Hazel-Loop> ... </Hazel-Loop>

Type=PRODUCTS

An extended abstraction of the selected loop, the primary "products" loop iterates over an explicit set of supplied SKUID or groups of SKUID.

Src=skuids

A semicolon-delimited list of SKUID to be looped.

Group=groupname

A single group name. Products looped will be those with groupname as their GROUP field value. This is equivalent to a query loop with a spec of "+GROUP=groupname" -- with the restrictions that all products of a certain group must be contiguous in the products file, and there is a maximum of 100 matches. Better to buy a search key and use the query loop!

All

If this attribute is given in a products loop, Hazel slurps in all products in your products file. Useful for the distributed sample page, or if you have only a handful of products you wish to display. If you have many products, be aware that this could be an awful big loop. Available as of H3/3.471 and H4/3.9AD.

The products loop is the basic way to create dynamic catalogs with Hazel. Its drawback is that it requires you to explicitly specify a list of SKUID. The "group" attribute is useful to a point, but for easier maintenance we suggest use of the query loop below.

<Hazel-Loop> ... </Hazel-Loop>

Type=QUERY

The "query" loop iterates over all products matching a given Hazel search engine specification.

Spec=searchquery

A fully-qualified Hazel search spec. For example, "+PRICE>100 +PRICE<200" would loop over all products with a price greater than 100 and less than 200. Use of the query loop requires purchase of a Hazel search engine key.

MaxHits=howmany

Restrict number of matches (and thus iterations/loops) to this number. It defaults to 100, so if you want more, you'll have to specify some very large number.

Sequential

If this attribute is given, then Hazel stops searching after the first product which fails to match after she's found matches. So, all the matching items must be grouped together contiguously in your products file. This is a dubious optimization flag, documented only for the sake of completeness.

Full utilization of the query loop requires an understanding of Hazel's search engine. Once you grok the basic structure of search specifications, the query loop is a powerful tool for creating dynamic "aisles" within your store. Mastery of the query loop will reduce catalog updates to simply adding new products to your products file.

<Hazel-Loop> ... </Hazel-Loop>

Type=OPTIONED

An "optioned" loop constructs a list of optioned products according to your specifications of a base SKUID and a list of option codes, then loops over each of them. Use of the optioned loop requires purchase of a Hazel options key.

Base=skuid

The base SKUID for the optioned products constructed for looping.

Options=options

A semicolon-delimited list of option codes. Each will be added as a suffix of the BASE SKUID, resulting in one new optioned product per option code being looped.

The optioned loop is useful if you'd like to present pre-constructed optioned products to a shopper, and you can nest loops to create optioned products with multiple option codes. However, most merchants favor presenting options as drop-down lists selectable by the shopper. For that, you want the options loop.

In any case, use of the options loop requires some familiarity with Hazel's optioned products feature.

Word Loops

The second basic type of loop is a "word" loop. Instead of iterating (a fancy word for "looping") over products, a word loop provides other data to be interpolated (a fancy word for "replaced") within its body.

The first word loop was the "notes" loop, which allowed the shop designer to show a list of order notes-- information about an order to which a shopper (or shopkeeper's order processor) might want to be alerted. From the notes loop grew a variety of loops iterating over catalog (and other) data.

<Hazel-Loop> ... </Hazel-Loop>

Type=string

One of notes, word, file, dump, options, and currency.

Each of the various "word" class of loops has varied attributes available, detailed below. The commonality between them all is that the loop provides certain %HZ tokens (often %HZH_WORD, for example) to be used in the loop body to represent the rows of data you're looping.

<Hazel-Loop> ... </Hazel-Loop>

Type=NOTES

The notes loop iterates over notes accumulated for the current order.

The context of a note loop is the list of current order notes. These are added through Hazel's rules files, or can be attached to specified products in the products file by adding a NOTE field. %HZH_NOTE in the Hazel-Loop body is substituted with each order note.

The current "loop number" can be accessed within the loop body with %HZH_NOTE_LOOP_COUNT. After the loop, you can use %HZH_NOTE_LOOP_TOTAL to find out the total number of iterations which occurred.

<!-- A simple bullet list of order notes.  -->

<ul>
<Hazel-Loop Type="Notes">
<li>%HZH_NOTE</li>
</Hazel-Loop>
</ul>

<p>%HZH_NOTE_LOOP_TOTAL order note(s).</p>

<Hazel-Loop> ... </Hazel-Loop>

Type=WORD

The word loop iterates over any group of words you specify.

Src=words

A semicolon-delimited list of words.

A word loop replaces %HZH_WORD in each iteration with each semicolon-delimited word given.

<!-- This loop will produce a bulleted list of the words -->
<!-- FOO, BAR, and BAZ. -->

<ul>
<Hazel-Loop Type="Word" Src="FOO;BAR;BAZ">
<li>%HZH_WORD is one of "FOO", "BAR", or "BAZ"</li>
</Hazel_Loop>
</ul>

The current "loop number" can be accessed within the loop body with %HZH_WORD_LOOP_COUNT. After the loop, you can use %HZH_WORD_LOOP_TOTAL to find out the total number of iterations which occurred.

<Hazel-Loop> ... </Hazel-Loop>

Type=FILE

The file loop reads in a file (from hazel-cat/loops), and for each iteration breaks a line into words.

Src=file

The name of a file in your hazel-cat/loops directory.

HZML

Include this attribute if you'd like each line to be rendered as HZML. Each line is rendered individually at the start of each loop, and only HZML tokens (not tags or element blocks) are rendered.

Size=number[%]

Either an explicit number of lines to read from the file or (if a percentage) a percent of the total lines in the file. The lines are chosen at random.

Basedir=path

H4 only; an alternate base for the relative src filename. Must be under either your hazel-doc or hazel-cat directories.

The file loop reads in a file (which must be located in your hazel-cat/loops directory) and for each line in that file renders the body of the Hazel-Loop. Within the body, tokens %HZH_WORD1 through %HZH_WORDx may be used to access each semicolon-delimited word 1-x on each line.

Prior to Hazel 3.426, only %HZH_WORD1 through %HZH_WORD9 could be accessed. Get a later version if you have more than 9 words on a line!

As of Hazel 3.422, the current "loop number" can be accessed within the loop body with %HZH_FILE_LOOP_COUNT. After the loop, you can use %HZH_FILE_LOOP_TOTAL to find out the total number of iterations which occurred.

The file loop is best explained by looking at the examples in your hazel-cat/templates/checkout.html template. It is used to produce the drop-downs of available states, countries, shipping methods, and so forth.

As of Hazel 3.496/3.9CV, each unparsed line of a looped file can be accessed with %HZH_LINE.

The following is an example using a file loop of country codes and names to create a drop-down select box in HTML. Each line of the "countries.txt" loop file is of the format CountryCode:Country Name.

<!-- Start an HTML select block. -->
<select name="SHIP_COUNTRY">

<!-- Our first, default option.  Either "choose one", -->
<!-- or fill in the last choice if there was one.  -->

<option value="%HZE_SHIP_COUNTRY">
<Hazel-Choice Token="%HZE_SHIP_COUNTRY"
 True="Previous Choice: %HZE_SHIP_COUNTRY_NAME"
 False="Please Choose a Country">

<!-- Just a dummy separator option entry. -->
<option value="">--

<!-- The guts, loading an option for each line of the countries -->
<!-- loop file.  For each, %HZH_WORD1 will be the country code, -->
<!-- and %HZH_WORD2 a pretty-looking full name for the country. -->

<Hazel-Loop Type="File" Src="countries.txt">
<option value="%HZH_WORD1">%HZH_WORD2
</Hazel-Loop>


<!-- End the select block. -->
</select>

<Hazel-Loop> ... </Hazel-Loop>

Type=DUMP

Primarily for debugging purposes, the DUMP loop allows you to see all the variables in a given %HZ token namespace.

Root=namespace

One of "Shopper" (%HZE), "Input" (raw CGI query info), "Cookies" (all HTTP cookies sent this session), "Hazel" (%HZH), "Variables" (%HZV), "Totals" (%HZT), "URL" (%HZU), or "Arg" (all input fields prefixed by ARG_).

Each iteration of a dump loop provides %HZH_DUMP_KEY and %HZH_DUMP_VAL tokens specifying the name and value of each entry in the given root namespace.

<!-- This loop will dump out all the data thus far entered by -->
<!-- or for the current shopper. -->

<Hazel-Loop Type="Dump" Root="Shopper">
%HZH_DUMP_KEY = "%HZH_DUMP_VAL";<br>
</Hazel_Loop>

<Hazel-Loop> ... </Hazel-Loop>

Type=OPTIONS

The options loop iterates over all option information for a particular list or group of options.

Src=option_codes

A semicolon-delimited list of option codes from your options file.

Group=option_groups

A semicolon-delimited list of groups within your options file. All option codes within those groups will be looped.

Each iteration of an options loop provides %HZH_WORD1 (the option code itself) and %HZH_WORD2 (the option description) tokens to use in its body.

<!-- Start an HTML select block with a name that will     -->
<!-- indicate to Hazel we want to add an optioned variant -->
<!-- of SKUID "FOO" to the shopper's cart. -->
<select name="OPTIONED_FOO">

<!-- Just some GUI stuff so the shopper gets the hint -->
<!-- that they should be choosing a color. -->

<option value="">Please Choose a Color
<option value="">--

<!-- Load all the options under the [COLORS] header in our -->
<!-- options file. The value for each HTML option will be  -->
<!-- the option code, while the text displayed will be the -->
<!-- option's description. -->

<Hazel-Loop Type="Options" Group="COLORS">
<option value="%HZH_WORD1">%HZH_WORD2
</Hazel-Loop>


<!-- End the select block. -->
</select>

<Hazel-Loop> ... </Hazel-Loop>

Type=CURRENCY

The currency loop iterates over all the currencies available through your catalog's currency.rules file.

Each iteration of an currency loop provides %HZH_WORD1 (the currency code), %HZH_WORD2 (its exchange rate relative to your base currency) and %HZH_WORD3 (the name of the currency) tokens to use in its body.

<!-- Start an HTML select block with a name that will  -->
<!-- indicate to Hazel the default currency desired by -->
<!-- the shopper.  This will have no direct effect on  -->
<!-- catalog prices, but will influence the default    -->
<!-- exchange rate for the Hazel-Currency HZML tag. -->
<select name="CURRENCY">

<!-- Just a prompt for the bucket of hair. -->
<option value="">Please Choose Your Currency
<option value="">--

<!-- Load all available currencies.  The value for each -->
<!-- HTML option will be the currency code, with the    -->
<!-- label showing the verbose name of the currency and -->
<!-- the listed exchange rate relative to a fixed base  -->
<!-- currency of USD (United States Dollars.)  -->

<Hazel-Loop Type="Options" Group="COLORS">
<option value="%HZH_WORD1">%HZH_WORD3 (1usd == %HZH_WORD2%HZH_WORD1)
</Hazel-Loop>

<!-- End the select block. -->
</select>


Getting Started HZML Rules Extras Advanced Reference
Download
Walkthrough
Configuration
The Products File
Order Reporting
Upgrading
Known Problems
Actions
HZML Tokens
HZML Tags
HZML Loops
HZML & HAM
Overview
Shipping
Sales Tax
Discounts
Surcharges
Tweaking
Customization
Input Fields
Softgoods
Search Engine
Optioned Products
Plugins
Design Tips
Themes
Currency
Payment Methods
Coupons
Regular Expressions
Perl API
hazel.config
Templates
HTML Basics
CGI and You
ChangeLog

Hazel Home - Help Contents - Searchable Knowledge Base - Live Technical Support