![]() |
VTML Tips and Techniques: General |
|
Once the site at the new server is ready, this message will automatically disappear!
Meanwhile, you can see how the move is progressing at the status page.
|
Home | VTML section | HTML section |
||
Variable names |
I haven't found any formal description of variables and how they're used in VTML but it's useful to sum up a few facts I determined largely by trial and error (and some systematic testing):
A few examples; all preceded by the following set of assignments: <WIZSET a = 1> <WIZSET a/8 = 8> <WIZSET a_8 = 5> These examples nicely illustrate how the parser behaves with respect to variable names and expressions; they also illustrate why a consistent coding style putting spaces around operators in expressions is important for not confusing yourself.
|
|
Two Lists |
The Editorlayout section already explains a couple of techniques for the DropDown control which can be used to let the user choose one of a set of values. But what if HTML defines a fixed set of possible values for an attribute but a particular browser allows a superset of that list? The answer is to use two DropDown controls, both not editable (and both with and empty entry at the top if the attribute is not required). The technique involves three sections: Editorlayout, Attributes and Taglayout. Let's take the ALIGN attribute of the IMG tag as an example. HTML 4.0 allows five different values: top, middle, bottom, left and right. But Netscape, MS Internet Explorer and WebTV have a few more possibilities: absbottom, absmiddle, baseline and texttop (though it's unclear which browser version actually supports what). First of all, as even the original VTML documentation mentions, you can use the ATTRIBUTES section to assign a tag attribute (when editing the tag) to two (or more) controls. So on the main tab of my Img.vtm tag editor I have a DropDown with just the standard HTML values (plus empty): |
|
<CONTROL TYPE="DropDown" NAME="dropAlign" WIDTH=100 ANCHOR="lblAlign" CORNER="NE">
<ITEM VALUE="" CAPTION="">
<ITEM VALUE="left" CAPTION="left">
<ITEM VALUE="right" CAPTION="right">
<ITEM VALUE="top" CAPTION="top">
<ITEM VALUE="middle" CAPTION="middle">
<ITEM VALUE="bottom" CAPTION="bottom">
</CONTROL>
|
|
Then on the Browser-specific tab I have another DropDown, with the extended set: |
||
<CONTROL TYPE="DropDown" NAME="dropAlignOther" WIDTH=100 ANCHOR="lblAlign" CORNER="NE">
<ITEM VALUE="" CAPTION="">
<ITEM VALUE="left" CAPTION="left">
<ITEM VALUE="right" CAPTION="right">
<ITEM VALUE="top" CAPTION="top">
<ITEM VALUE="texttop" CAPTION="texttop">
<ITEM VALUE="middle" CAPTION="middle">
<ITEM VALUE="absmiddle" CAPTION="absmiddle">
<ITEM VALUE="baseline" CAPTION="baseline">
<ITEM VALUE="bottom" CAPTION="bottom">
<ITEM VALUE="absbottom" CAPTION="absbottom">
</CONTROL>
|
|
Note that the controls have different names, but in the ATTRIBUTES section I assign the attribute ALIGN to both these controls: |
||
<ATTRIB NAME="ALIGN" CONTROL="dropAlign"> ... <ATTRIB NAME="ALIGN" CONTROL="dropAlignOther"> |
|
Now when editing an exiting tag, the fact that the DropDowns are not editable will make sure that a value not occuring in the list is not picked up; if the user had typed a completely different value, both DropDowns would show the empty value. If the tag had a browser-specific attribute value, the DropDown on the Browser-specific tab would show that value, but the DropDown on the main tab would still show the empty value. And if the tag had an attribute value that occurs in both lists, both DropDowns would show that value. (Note: currently there is no way for a VTM to edit an existing IMG tag since this editor is built-in. But I'm hoping fervently the next version of HomeSite will give us the option to choose between the built-in editor and our own version for editing, giving us much more flexibility and a better way to keep up with HTML developments.) When writing the new (or edited) tag, the TAGLAYOUT looks at the values in both DropDowns and takes a decision: If a browser-specific value has been chosen, that takes precedence; is that is not the case but both are non-blank, the HTML DropDown on the main TabPage takes precedence; and if the latter is empty but the browser-specific one is not, the browser-specific one is used: |
||
<WIZIF Find(dropAlignOther, 'abs') OR Find(dropAlignOther, 'base') OR Find(dropAlignOther, 'text')>
<WIZSET Align = dropAlignOther>
<WIZELSEIF dropAlign NEQ ''>
<WIZSET Align = dropAlign>
<WIZELSEIF dropAlignOther NEQ ''>
<WIZSET Align = dropAlignOther>
</WIZIF>
|
|
So if at least one of the DropDowns has a value, the variable Align will be assigned a value; if both are empty, Align will remain empty as well. This is used to decide whether or not to write the attribute: |
||
<WIZIF Align NEQ ''>$$SpacingGap$${DefaultCase('ALIGN')}=$$Align</WIZIF>
|
Was that value |
Here's another technique that involves several sections, in this case EDITORLAYOUT, ATTRIBUTES and TAGLAYOUT. This is about how to determine whether an attribute value was changed (or how to hide a control). When working on the tab for a Conditional loop in the WIZLOOP tag editor (part of my package of VTML Tag Definitions) I realized that in the TAGLAYOUT section I would need to make a decision to give precedence to the field with the whole condition in string form or the fields in the condition builder panel. It's easy enough to just always give precedence to the string field. But that's not very user-friendly: when I'm editing a condition I could either just edit the string field or decide to use the condition builder to rebuild the condition of build a new one; but in the latter case I'd have to go back to clear the string field or I'd just get my old condition back. So... wouldn't it be nice to give precedence to the string field only if it's changed when both areas contain input? To do that, I'd need to remember the value of the string field before the user touched it. What I found after a lot of puzzling and testing could be either called a technique or a dirty trick - depending on your preference. I'm certainly violating some rules - but it doesn't seem to break anything, so let's just call it a technique for now. ;-) To determine whether an attribute has changed, I'll need to compare the current value with the previous value, so I need two controls: one to "remember" the old one, and one the user can change. My first approach was to build on the technique described for Display-only controls: use a label to hold the current value, so that could be compared with the string from the textbox used for input. Nice idea only it didn't work. I found out that while a label can be used to display a value, it cannot be used to store a value. When using the value of a label in an expression the result is always an empty string. In other words: a label control is write-only. Well, I know I can query the value of a textbox, so I'll need to use a second textbox - but prevent the user from touching it: only the "real" should be editable. So I could make the comparison textbox non-editable. But now I still have a user interface problem: having two textboxes on the screen with the same value can be really confusing - even if only one is editable. So I wanted to hide the memory textbox. Alas, there's no HIDE attribute for controls in VTML. But guess what? I found I can hide a control all the same. And this is where it gets a little dirty. Here's a code fragment from the EDITORLAYOUT section of the WIZLOOP editor: |
|
<CONTAINER TYPE="Panel" NAME="pnlCondition" CAPTION=" Condition " WIDTH="MAXIMUM" HEIGHT=55 HORIZRESIZE="BODY" MAXWIDTHPADDING=10 RIGHT=10 DOWN=5>
<CONTROL TYPE="TextBox" NAME="txtCondition" WIDTH="MAXIMUM" RIGHT=20 DOWN=20>
<CONTROL TYPE="Image" WIDTH=12 HEIGHT=12 ANCHOR="txtCondition" CORNER="NW" RIGHT=-15 FILEPATH="Images/Asterisk_g.bmp" TRANSPARENT="Yes">
<!-- Use TextBox control outside of display area to save current value! -->
<CONTROL TYPE="TextBox" NAME="saveCondition" WIDTH=1 HEIGHT=1 ANCHOR="pnlCondition" CORNER="NW" RIGHT=-20 DOWN=-20>
</CONTAINER>
|
|
Note what I'm doing to hide the "saveCondition" textbox: First of all, I'm giving a hight and width of 1 so it'll be really small (it can still hold a value). Then I'm using the NW corner of the panel the textbox is defined inside of, and positioning the textbox 20 pixels up and to the left of that corner: in other words, it ends up outside of the panel it's supposed to be in - and this effectively hides the field. So now that hiding the save field is taken care of, the rest is rather straightforward. In the ATTRIBUTES section, the current condition is assigned both to the input field and to the save field: |
||
<!-- Conditional loop --> <ATTRIB NAME="CONDITION" CONTROL="txtCondition"> <ATTRIB NAME="CONDITION" CONTROL="saveCondition"><!-- save state before editing --> |
|
And finally here's the decision-making bit in the TAGLAYOUT section: |
||
<WIZELSEIF loopType EQ 'ConditionalLoop'>
<WIZIF (txtCondition NEQ '') AND (txtCondition NEQ saveCondition)>
<WIZIF 1> $${DefaultCase('CONDITION')} = '$$txtCondition'</WIZIF>
<WIZELSE>
... (building condition from the condition builder fields)
</WIZIF>
...
|
|
Like so many techniques: once you know how to do it, it's really simple.
|
||
Preselecting |
While working on a better interface for the Tag Chooser, I hit on an idea: when you edit a tag and the tag editor has TabPages corresponding to different types of that tag, the appropriate tab will be selected automatically. Now wouldn't it be nice if you could have the Tag Chooser call up such a tag editor with a particular tab preselected? Well, if the tab corresponds to an attribute, you can! Although the main focus of the technique is the Tag Chooser (MarkUpTags.vtm), it also involves the EDITORLAYOUT and ATTRIBUTES section of a tag editor, so that's why you find it here. The following bit of code lets you choose my WIZLOOP tag editor with either the Index, Conditional or List loop tab preselected: |
|
<E CAPTION="WIZLOOP Index" VALUE='<WIZLOOP TYPE="IndexLoop"' HELPFILE='Docs/VTMLTags/MKwizloop.html'> <E CAPTION="WIZLOOP Condition" VALUE='<WIZLOOP TYPE="ConditionalLoop"' HELPFILE='Docs/VTMLTags/MKwizloop.html'> <E CAPTION="WIZLOOP List" VALUE='<WIZLOOP TYPE="ListLoop"' HELPFILE='Docs/VTMLTags/MKwizloop.html'> |
|
What's that? WIZLOOP does not even have a TYPE attribute. Well, if it had, this would be all there is to it. (I'm using the same technique for Input.vtm to preselect a tab for a particular form element). For WIZLOOP it requires an extra bit of code in the ATTRIBUTES section of the tag editor to fool it into thinking there actually is a TYPE attribute: |
||
<ATTRIB NAME="TYPE" CONTROL="loopType"> <!-- allows tab selection from the tag chooser dialog --> |
|
The name of the control in this ATTRIB tag corresponds to the TabDialog which is called "loopType": |
||
<CONTAINER TYPE="TabDialog" NAME="loopType" ... |
|
and the names of the TabPages within that TabDialog correspond to the TYPE attributes mentioned in the VALUE attributes of the <E> tags in MarkUpTags.vtm: |
||
<CONTAINER TYPE="TabPage" NAME="IndexLoop" CAPTION="Index Loop"> |
Contributions! |
Do you have any VTML Tips or Techniques to share? If it's for the General section, use the following email link, otherwise go to the page corresponding to the section it's about and use the Contributions! mail link from there, so your mail will have the correct subject. Please explain why it's such a good tip, and illustrate with example code where appropriate. Also let me know whether you want you email address mentioned here, or only your name. Send your contribution to: The VTML Tips and Techniques sections are: |