HTML Template Meets Data
Many Webspeed programs incorporate HTML into the programming, which makes it difficult for a the UI designer to change the look of the program's results without being a Webspeed programmer too.
Add to that, sometimes the HTML isn't related to a browser - but to an email.
So the question of the hour is - how do we change the look and feel of an HTML/javascript result without changing the coding (Webspeed or ABL Background process?)
The way to do this is with the Voleso classes (that are open source and free from me at scott_auge@yahoo.com, just ask for them!)
Take the below example: The UI designer can dress up the HTML all they want. Then with agreed upon names for the data (such as {$ThankYouMessage} that might be from the database) and repeating sections (the {section name=name} ... {/section}), the Webspeed programmer can design a program that handles that information for population from the database and algorithms.
Take for example the very simple HTML for an email thanking a customer for the purchase of some items below. This would be developed by a UI designer and an ABL programmer with agreed upon names for the data (aka {$ThankYouMessage}) and agreed upon sections ("bom," "comment," and "addon").
After the data elements have been entered, the UI designer can change the template how ever they wish without recompiling the ABL coding.
The Template
/tmp/scott.html
<html>
<body>
<h1>{$ThankYouMessage}</h1>
<table>
{section name=bom}<tr>
<td bgcolor="#cccccc">{$Item}</td>
</tr>
<tr><td><pre>
{section name=comment}Comment: {$Comment}<br>{/section}
</pre></td></tr>
<tr><td><pre>
{section name=addon}Add On Desc {$Description} Price {$price}<br>{/section}
<pre></td></tr>{/section}
</table>
{section name=delete}Should be deleted{/section}
<p>Thank you,</p>
<p>{$YourCompany}</p>
</body>
</html>
You can see a "bom" section for a list of items that were sold to the customer. For each item, there is a comment section and add on pricing section - so sections can be nested together. There can be multiple comments and multiple addon costs with a section. Finally there is a section named "delete" which is suppose to show that if a section isn't used, it is programmatically easy to deal with it.
The Result
<html>
<body>
<h1>Thank you for your order!</h1>
<table>
<tr>
<td bgcolor="#cccccc">Part-1</td>
</tr>
<tr><td><pre>
Comment: Hi there 1-1<br>Comment: Hi there 1-2<br>
</pre></td></tr>
<tr><td><pre>
Add On Desc whalawhala-1 Price 48.99<br>Add On Desc whalawhala-2 Price 58.99<br>Add On Desc whalawhala-3 Price 50.99<br>
<pre></td></tr><tr>
<td bgcolor="#cccccc">Part-2</td>
</tr>
<tr><td><pre>
Comment: Hi there 2-1<br>Comment: Hi there 2-2<br>
</pre></td></tr>
<tr><td><pre>
Add On Desc whalawhala-1 Price 16.99<br>Add On Desc whalawhala-2 Price 31.99<br>Add On Desc whalawhala-3 Price 44.99<br>
<pre></td></tr><tr>
<td bgcolor="#cccccc">Part-3</td>
</tr>
<tr><td><pre>
Comment: Hi there 3-1<br>Comment: Hi there 3-2<br>
</pre></td></tr>
<tr><td><pre>
Add On Desc whalawhala-1 Price 60.99<br>Add On Desc whalawhala-2 Price 44.99<br>Add On Desc whalawhala-3 Price 52.99<br>
<pre></td></tr><tr>
<td bgcolor="#cccccc">Part-4</td>
</tr>
<tr><td><pre>
Comment: Hi there 4-1<br>Comment: Hi there 4-2<br>
</pre></td></tr>
<tr><td><pre>
Add On Desc whalawhala-1 Price 18.99<br>Add On Desc whalawhala-2 Price 29.99<br>Add On Desc whalawhala-3 Price 34.99<br>
<pre></td></tr>
</table>
<p>Thank you,</p>
<p>Amduus Information Works, Inc.</p>
</body>
</html>
Seen as a web page:
By having a template, the UI designer can change the HTML/Javascript all around to highlight upcoming specials or other items that might be of interest. The UI designer can then write that template over /tmp/scott.html and when an email needs to go out, the program will pick up the new look and feel.
The Program
Here is a simple program illustrating how to achieve the above.
define variable Test as com.amduus.voleso.clsVoleso no-undo.
define variable Comment as com.amduus.voleso.clsVoleso no-undo.
define variable AddOn as com.amduus.voleso.clsVoleso no-undo.
define variable BOM as com.amduus.voleso.clsVoleso no-undo.
define variable Counter as integer no-undo.
define variable AddonIter as integer no-undo.
define variable CommentIter as integer no-undo.
Test = new com.amduus.voleso.clsVoleso("/tmp/scott.html").
Test:AssignVar("ThankYouMessage", "Thank you for your order!").
Test:AssignVar("YourCompany", "Amduus Information Works, Inc.").
// Starting our items as a do instead of a for each
bom = new com.amduus.voleso.clsVoleso(Test:GetSection("bom")).
do Counter = 1 to 4:
if Counter > 1 then bom:NextSection().
// Set our "Item"
bom:AssignVar("Item", "Part-" + string(Counter)).
// Grab comment
comment = new com.amduus.voleso.clsVoleso(bom:GetSection("comment")).
do CommentIter = 1 to 2:
if CommentIter > 1 then comment:NextSection().
comment:AssignVar("Comment", "Hi there "
+ string(Counter)
+ "-"
+ string(CommentIter)).
end.
// Grab Addon
addon = new com.amduus.voleso.clsVoleso(bom:GetSection("addon")).
do AddonIter = 1 to 3:
if AddonIter > 1 then addon:NextSection().
addon:AssignVar("Description", "whalawhala-" + string(AddonIter)).
addon:AssignVar("Price", random(1, 99) + .99, "99.99").
end.
// Attach it to bom
bom:ApplySection("comment", comment).
bom:ApplySection("addon", addon).
delete object comment.
delete object addon.
end. // do Counter
Test:ApplySection("bom", bom).
Test:DeleteRemainingSections().
Test:HTMLRender("/tmp/scott_rendered.html").
First of all you can see four instances of the Voleso class are needed. One for the template as a whole called "Test," and three for the sections "bom," "item," and "addon." Yes, one can reuse the classes but I wanted a simple example.
Lets go through this - first we initialize one of the objects through a new with a file name and we call that Test. (An upcoming feature will be initializing it through a record as I plan on writing an ecommerce system with this.)
One can use :AssignVar(VariableName, VariableData) for elements within that section. (The file as a whole is considered by Voleso as a section.)
But then we have a loop with n iterations! How do we handle that? By using the {section name=xxx} and {/section} delimiters. One can take a subsection out of another section with :GetSection(SectionName). If you are in a loop, use :NextSection() which will make new section for :AssignVar() to use. Once done, apply the section to the section it was :GetSection()'ed from with :ApplySection(SectionName, SectionObject). Congrats! You did your first loop!
As for the comment and addon sections, a section can be in a section which in it's self is part of a section.... I think you get the idea.
Finally, one can have a section that is not used due to the algorithm, this one is called "delete." The method :DeleteRemainingSections() will eliminate all the sections that have not been :ApplySection()'ed.
The :HTMLRender() has two overloaded methods, one for Webspeed and one for writing to a file. In this example we write to /tmp/scott_rendered.html which will be used with the email.
Conclusion
So we have an easy to use system that can be put into files (reports or email) or used with Webspeed programs. The HTML/Javascript is totally out of the ABL programmers hands, so the template can be changed in any way, provided the data and loops negotiated at the beginning remain the same, without ABL programmer's recompiling the program. Separation for the UI designer and the ABL programmer has been achieved!
Solid tool, nice work!