Associated text

$[Associated text {VAR}]$
$[Associated text1 {VAR1}||Associated text2 {VAR2}]$
$[Associated text1 {VAR1}||Associated text2 {VAR2}||Default text]$

When designing a flipomatic interface you will almost certainly encounter situations where you want to display certain things only if certain fields exist, whether it is HTML markup or plain text. This inevitably occurs when you want to display labels for each of your fields. Consider the following detailed display for our fictional book database. Our database contains many fields but not all are required, some may be blank:

Author: Stewart, Martha
Title: Martha Stewart's guide to financial success.
Publisher: Leavenworth Books
Date: 1990
Series:  
Notes:  
Subjects: Insider trading

Gah! Some of my books have series and notes but this one doesn't. How do I get rid of those extraneous labels!? Thank goodness for associated text. You can associate certain text or markup with certain substitution variables by packaging them together within the dollar-bracket tokens. If the substitution variable does not exist, the entire string disappears. By modifying our template to look like this:

[Template !DEFAULT#1]
<html>
<head>
<title>Detailed View</title>
</head>
<body>
<table>
<tr>
<td align="right"><b>Author: </b></td>
<td>{AUTHOR}</td>
</tr>
<tr>
<td align="right"><b>Title: </b></td>
<td>{TITLE}</td>
</tr>
<tr>
<td align="right"><b>Publisher: </b></td>
<td>{PUBLISHER}</td>
</tr>
<tr>
<td align="right"><b>Date: </b></td>
<td>{DATE}</td>
</tr>
$[<tr>
<td align="right"><b>Series: </b></td>
<td>{SERIES}</td>
</tr>]$
$[<tr>
<td align="right"><b>Notes: </b></td>
<td>{NOTES}</td>
</tr>]$
$[<tr>
<td align="right"><b>Subjects: </b></td>
<td>{SUBJECTS*}</td>
</tr>]$
</table>
</body>
</html>


[Template SubjectRS]
{$Subject}<br>

... those nasty, naked labels disappear:

Author: Stewart, Martha
Title: Martha Stewart's guide to financial success.
Publisher: Leavenworth Books
Date: 1990
Subjects: Insider trading

Note that associated text brackets can encompass multiple lines.

Associated text is a far more powerful utility than it may first seem, and is probably the most complex and potentially confusing of all of flipomatic's features. Associated text—especially in conjunction with flags discussed below—provides the designer with the ability to perform conditional logic and branching (if - else if - else). Consider the expanded form of the associated text syntax:

$[Associated text1 {VAR1}||Associated text2 {VAR2}]$

This statement means that if {VAR1} exists, print it and its associated text. If it doesn't exist then print {VAR2} and its associated text if {VAR2} exists. If neither variable exists, then print nothing. A similar block of perl code might look like this:

if (defined $var1) {
   print "Associated text1 $var1";
} elsif (defined $var2) {
   print "Associated text2 $var2";
}

You can string together as many associated text blocks as you wish. You can also define a final block, not associated with any variable, to print if all other variables do not exist (for programmer's this is analogous to a SWITCH statement's DEFAULT case). This lengthy statement:

$[Associated text1 {VAR1}||Associated text2 {VAR2}||Associated text3 {VAR3}||Associated text4 {VAR4}||Default text]$

would be roughtly equivalent to the following perl code:

if (defined $var1) {
   print "Associated text1 $var1";
} elsif (defined $var2) {
   print "Associated text2 $var2";
} elsif (defined $var3) {
   print "Associated text3 $var3";
} elsif (defined $var4) {
   print "Associated text4 $var4";
} else {
   print "Default text";
}

Associated text is not limited to data substitution variables. All Flipomatic substitution variables work with associated text. You can generate different HTML depending on what form elements a user has filled in:

$[Associated text1 {&sort}||Associated text2 {&title}]$

The following example generates code based on system variables. Note this is a VERY common Flipomatic idiom. You will definitely be doing this if you want to add any kind of navigational abilities to your site:

$[<a href="{FULLURL}?page={_NEXTPAGE}">Next Page</a>]$

This string will only generate a link to a next page if a next page actually exists (one could also generate a "gray-out" version of the link as a second alternative). So if the user is on the last page of a multipage search result, or if their search only retrieved a single page of results, they will not be prompted to go to a next page that doesn't exist.

Here is how associated text works. If any unresolved substitution variables remain in a block of associated text, the entire block will disappear and any alternative blocks will be evaluated instead. Any substitution variables ({& ...}, {_ ...}, etc.) that have no corresponding value will delete that block of associated text.

That's right. Variables. Plural. Associated text blocks can contain more than one substitution variable, as in our last example above with the Next Page link. That block contains a user variables AND a system variable. So which one is "associated" with the text?

Answer: they both are. If either one of them do not exist, the entire block will evaporate. Here is the largest source of confusion users encounter when dealing with associated text and it's important to know how to resolve it. How to designate which variables trigger the associated text and which ones do not. Here's how.

Recall many substitution variables provide a mechanism for defining alternative text, strings of text which should be generated if the variable has no value. {AUTHOR|No author} will generate the string "No author" if that particular record does not have any value in the Author field. Since any alternative text is evaluated before associated text blocks are, substitution variables with alternative text will never trigger the deletion of associated text blocks. The alternative text will be swapped in instead. You can even define zero-length alternative text, e.g, {AUTHOR|}

As it turns out, defining blank alternative text is the best way to assure those variables do not trigger deletion of associated text blocks if those variables are blank.

$[{VAR1|} text {VAR2} text {&param|} text ]$

In this example only {VAR2} will cause the entire block of associated text to disappear if it is blank. {VAR1} and {&param} will simply disappear if they do not exist. This construct is used most frequently with query string variables, particularly those which correspond to HTML form search input boxes. Generally the fact that a user has not typed anything into a particular search box should not impact how the data is displayed in HTML. It affects the Flipomatic query that retrieves the information from a METS file, but not usually how the results are displayed.

With this in mind, let's revisit some advice I gave earlier. I recommended that users should always define a user-defined variable called FULLURL in the [General Parameters] portion of their configuration file. This url would contain a complete query string consisting of all of the html search form elements used. I would amend that example slightly by supplying empty alternative text to each of the query string parameter substitution variables:

[General Parameters]
PageSize    30
FULLURL     {_SCRIPTURL}?author={&author|}&title={&title|}&publisher={&publisher|}
...
That way, in a template like this:
[Template DEFAULT]
<html>
...
$[<a href="{FULLURL}&page={_NEXTPAGE}">Next page</a>]$

those query string substitution variables imported by way of {FULLURL} will not cause the Next Page link to disappear simply because the user did not type any search terms into some or all of the search text boxes. Only the {_NEXTPAGE} system variable will trigger the alternative text deletion if it does not exist, which is exactly what we want.

One final point about alternative text, a rather important one that probably should not have been left until last, but oh well. You cannot nest alternative text, that is you can't use one set of alternative text blocks inside of another.

This is illegal: $[text {VAR1} $[text {VAR2}]$ etc. ]$

Also be wary of accidental nested text blocks imported via template variables or group subvariables.

Flags, redux

{|&param|}, {|&param1|&param2|&param3|}
{|VAR|}, {|VAR1|VAR2|VAR3|}

There are actually many cases where nested associated text blocks would be a very useful thing. This is one of the things that flags are good for.

Recall our short definition of flags presented earlier. Flags simply disappear if their corresponding value exists. What good is that for? Flags are only useful when used in conjunction with associated text blocks. You can trigger which text displays by adding flags to the appropriate associated text block. This way you can display the correct associated text without actually inserting the value of that particular variable. This ability is more powerful and subtle than it may seem at first. Using simple and compound flags with associated text blocks gives you the ability to make conditional choices and add branching capabilitites to your template code.

Simple flags contain a single variable name: {|VAR|}. Comound flags contain multiple variable names: {|VAR|VAR2|VAR3|}. If any of the variable names in a compound flag evaluate to a non-blank value, the entire compound variable disappears (and thus will not trigger the deletion of its encompassing associated text block). To see how flags provide conditional processing consider the equivalent perl code for the following text block (and as an exercise see if you can work out the logical conditional steps for yourself by how the associated text blocks will disappear or not disappear depending on whether the flags exist):

$[{|VAR1|}{|VAR2|VAR3|VAR4|}Text block 1||
{|VAR5|}Text block2||
{|VAR1|}Text block3||
Default text block]$


if ((defined $var1) and ((defined $var2) or (defined $var3) or (defined $var4)) {
   print "Text block 1";
} elsif (defined $var5) {
   print "Text block 2";
} elsif defined $var1) {
   print "Text block 3";
} else {
   print "Default text block";
}

Flags can represent not only data variables, as illustrated above, but also system variables (to present different interfaces based on, say, whether there were any records retrieved from a search using {|_RECORDCOUNT|}), or query string parameter variables (based on the value a user selects from a drop-down list or checkbox button, or which text search forms they fill in ({|&checkbox|}).

Let's consider a real, live example which is actually not uncommon, where flags are required. In a typical library online catalog, publication information is usually presented in a standard form, e.g.,

Place of publication : Name of publisher, Date of publication.

A colon appears before the name of the publisher and a comma before the publication date. At first glance you might think you could get away with a simple template like this:

[Template GROUP]
...
<tr><td>Publication statement:</td>
<td>{PUBPLACE} : {PUBNAME}, {PUBDATE}.</td></tr>

And this would work fine if you were sure every entry in your database contained values for all three fields. But what if some entries had no publisher name? Your display would end up looking like this:

Publication statement:   Chicago  :  ,  1964.

We are left with some unusual punctuation. At first one would think this problem could be solved using simple associated text blocks:

[Template GROUP]
...
<tr><td>Publication statement:</td>
<td>{PUBPLACE} $[: {PUBNAME}]$$[, {PUBDATE}]$.</td></tr>

If a comma comes before a date, why, only put one in if a date actually exists. And this almost works, except if there is no PubPlace field:

Publication statement:  : Harper,  1964.

Not only are we left with the colon at the front, but more likely than not, your entire table row would be enclosed in its own associated text block anyway so as not to trigger the "Publication statement: " label if there is no publisher, and this could result in illegal nested associated text blocks:

Illegal:
[Template GROUP]
...
$[<tr><td>Publication statement:</td>
<td>{PUBPLACE} $[: {PUBNAME}]$$[, {PUBDATE}]$.</td></tr>]$

There is actually a subtle conditional logic that is employed by online catalogs when displaying publication information and it goes something like this: If there is a publisher name and a publication place, print a colon before the publisher name. If there is a publisher name or a publication place and a publication date print a comma before the publication date. If there is either a publication place or a publisher name or a publication date, print a "Publication statement" label. In an HTML environment, that last would also need to take into account <tr>, <td>, </tr>, </td> opening and closing tags as well as a label. The equivalent perl code might look something like this:

if ((defined $pubplace) or (defined $pubname) or (defined $pubdate)) {
   print "<tr><td>Publication statement: ";
}

print $pubplace;

if ((defined $pubplace) and (defined $pubname)) {
   print " : ";
}

print $pubname;

if (((defined $pubplace) or (defined $pubname)) and (defined $pubdate)) {
   print ", ";
}

print $pubdate;

if ((defined $pubplace) or (defined $pubname) or (defined $pubdate)) {
   print ".</td></tr>";
}

(That last if block is there simply to close the <tr><td> opened in the first if statement).

Whenever you find yourself in a similar situation, or when you wish you could nest associated text blocks, flags will usually do just what you want. The technique is to break up an existing associated text block into small pieces, each piece being controlled by the appropriate combination of flags. It can be ugly and difficult to understand but it always works quite well. The previous example would be composed in a template like this (I've broken it up into multiple lines for clarity):

[Template GROUP]
...
$[{|PUBPLACE|PUBNAME|PUBDATE|}<tr><td>Publication statement: </td>
<td>]$
{PUBPLACE}
$[{|PUBPLACE|}{|PUBNAME|} : ]$
{PUBNAME}
$[{|PUBPLACE|PUBNAME|}{|PUBDATE|}, ]$
{PUBDATE}
$[{|PUBPLACE|PUBNAME|PUBDATE|}.</td></tr>]$

Yow! What a mouthful. Compare this with the example perl code and convince yourself this does what it's supposed to do. Let's close by considering three more examples almost identical to the one above. Try and figure out the template syntax for each example before clicking the link for the answer. If you can figure out these then rest assured you understand all there is to know about flags and associated text.

  • Online library catalogs typically display title-related information in this format:

    Title statement:   Main title  :  Subtitle  /  Statement of responsibility.

    Assume you can be confident that there will always be a title (and thus there will always be a label). Construct a template that will display appropriately given that there may not always be a subtitle and/or statement of responsibility. Assume your field names are TITLE, SUBTITLE, and RESPSTMT. Check Answer

  • Online library catalogs typically display pagination and other physical description information in this format:

    Description:   Pagination  :  Illustrations  ;  Size.

    Assume any combination of these fields may be present, or none of them. Also assume your field names are PAGINATION, ILLUSTRATIONS, and SIZE. Check Answer

  • Our first example describes how online catalogs typically display publication information. Some levels of bibliographic description also include details of manufacture (printing, distribution, etc.). Such information generally displays following the date and preceded by a space-colon-space, e.g.,

    Publication statement:   Chicago  :  University of Chicago Press,  1961  :  Printed by Hawthorne, Inc.

    Modify our first example to include this additional information. Assume any or all of the fields may be present, or none of them. Use the field names PUBPLACE, PUBNAME, PUBDATE and PRINTER. Check Answer