Understanding optionSplit

advertisement
Understanding optionSplit
Category: Typoscript
A fresh look at the basics of the Typoscript optionSplit expression
The TSref optionSplit entry serves well as an introduction to a powerful tool available to
Typoscript. Despite its numerous examples to aid in clarifying the unfortunate terminology (What's
the practical difference between a subpart and part? What does "the first part of the last value is
repeated before the last value" mean?), it left me more curious than confident. I was ready to try
some experiments of my own. My main goal was the find the boundaries of the optionSplit
expression and to see if those boundaries helped in understanding the optionSplit rules. If possible,
it would also be nice to have some sort of shorthand to represent patterns that can be rendered using
optionSplit so that one could quickly and easily locate the expression need to render it. Let's quickly
look at some terminology so we're talking about the same thing.
An optionSplit expression is one-line string with a number of splitters or dividers organizing
substrings into a hierarchy. We can call the full string the optionSplit expression or just the string.
The TSref uses the terms "parts" and "subparts" to break this main expression down into relevant
pieces. A "part" is a subexpression as determined by the location(s) of the |*| splitter. A "subpart" is
a part that has been further broken down by the || splitter, and contains no further optionSplit
operators.
The TSref does well to demonstrate the purpose of optionSplit. In the simplest terms it is to provide
a controlled structure for assigning attributes or values to a list of items (usually titles of pages for a
menu) according to the number of items in the list. This is achieved with two types of dividers or
splitters, which each split and prioritize the options according. The first divider is two horizontal
lines: ||. It, according to the TSref, subdivides the first, middle and last into subparts and we'll call it
the "subparts divider." This divider can, in reality, split more than three strings. The first, middle,
and last parts are split using the second divider: |*|. This is the "parts divider," however, it might be
easier to call it the "FML divider" (first, middle, last) since, as we shall see, this divider can only
occur twice in an optionSplit expression, and therefore only splits the first, middle and last. The
subparts divider, as previously mentioned, can occur any number of times in an expression,
something that is not explicited said about these dividers. Clearly neither NEEDS to occur in any
expression, as demonstrated by one of the first examples in the TSref:
temp.topmenu.1.NO {
backColor = red ....
}
There's no evidence of option-splitting occurring here, but all properties of .NO are parsed by
optionSplit, and thus the second line is a valid optionSplit expression as it produces controlled
output. Without either of the optionSplit dividers in the expression, the split output simply remains
the same for each menu item. The shorthand I'm going to use in this article would represent this
expression this way(note that the asterisk on the far right indicates repitition):
n|*||*| produces n*
Let's first look at how the parts splitter, aka the FML divider ( |*| ), behaves in simple expressions,
and then follow with thesubparts divider ( || ) since its behavior varies with the context it appears
in(ie whether it appears first, middle or last as determined by the FML divider). We are told that
optionSplit prioritizes the options of this divider in the order: last, first, middle.
first_part|*|middle_part|*|last_part
This means that if there were only one menu page grabbed by the HMENU (we'll continue using the
menu example as it is the most relevant), optionSplit would return: last_part. With two pages:
first_part, last_part. With three or more pages the first_part would occur in the first slot, the
last_part in the last and all middle pages would be middle_part since the middle repeats.
Additionally, with no middle_part:
first_part|*||*|last_part
the first_part would simply repeat until the last_part terminates the optionSplit. This expression
would be very useful for a menu where the items are separated by a horizonal line(often seen on
footers of webpages), like this:
Who | What | When | Where | Why | How
Each page title has a horizonal bar following it, except for the last. We could describe this in a more
useful shorthand like this: first..., second Since the last always has priority with the FML divider,
and we have a repeating value for all other pages, this menu is created like this:
lib.mainMenu = HMENU
lib.mainMenu.1 = TMENU
lib.mainMenu.1 {
SPC=|
expAll = 1
wrap = |
NO.allWrap = | ||*||*| |
NO.linkWrap= |
}
The | in the expression is the HTML character code for the horizonal line, spelled out so we
don't interfere with stdWrap or optionSplit. Without the subparts divider in action, the rules for the
FML divider can be summarized like this:
1. Priority is last, first, middle.
2. Middle will repeat as necessary.
3. If the middle value is empty, the first value will repeat until the last value. Since one of the
goal listed above was to define the limits of optionSplit we could add this rule as well:
4. If the first and middle values are empty, the last value will repeat. Or, more generally:
5. If any two of the first, middle or last parts (remember, only as differentiated by the FML
divider) are empty in an optionSplit statement, the place-value that is not empty will be
repeated. As we know, however, we could just repeat by leaving all dividers out, so this rule
is not going to be applied very often.
The subparts divider ( || ) does not always behave the same way. Its behavior varies with the context
in which it occurs. By context, in this case, we are referring to how the where in the expression it
occurs in relation to the maximum of two FML dividers. In the first and middle part or context
(with or without any FML dividers in the expression), the each value is activated in a first-come,
first-served manner. This means that:
first || second ||third || fourth
with a 3-page menu will render: first, second, third. With a 5-page menu, however, the last value
will repeat: first, second, third, fourth, fourth. In the same shorthand we used above we could
describe this type of menu like this:
x1||x2||x3...||xn produces x1,x2,x3,...xn*
In the "last" context, like this:
|*||*|first||second||third||fourth
the tables turn, however. Suddenly we have a last-come, first-served situation where the first value
repeats. What you see directly above with a 3-page menu will produce: second, third, fourth. With a
5-page menu we get: first, first, second, third, fourth. We'll describe this menu like this in
shorthand:
|*||*|x1||x2||x3||...xn produces x1*,x2,...xn
Things only become slightly more complex when we have subexpressions in each of the three parts.
The main rules still hold true:
1) the parts are prioritized last, first, middle,
2) the subparts are prioritized according to their context,
3) when there are enough values that a value needs to repeat, it comes from the lowest priority
subpart, or
4) if there is a middle, it will rotate or repeat as necessary.
These types of expressions would become increasingly difficult to describe in our shorthand. Here
is an attempt to demonstrate how optionSplit would prioritize each item in a longer expression:
8
9
3
4
5
6
7
2
1
string1|
|string2|
|string3|*
|string4|
|string5|*
|string6|
|string7
The "middle" part will continue to cycle through its values until each item has a value assigned by
optionSplit.
Feel free to e-mail me if this article has or hasn't helped you in understanding optionSplit, or if
there's something you'd like me to add.
Download