Pages within pages
Our discussion of outlines and outline renderers may have caused you to wonder as follows: "Clearly outlines can do wonderful things for me if my entire Web page consists of only one type of entity. For instance, the default outline rendering is great if my whole Web page is a bulleted list. But how does it help me include a bulleted list as part of a larger page? The table outline renderer is cute, but usually I don't want an entire page consisting of nothing but a single table, do I? So what should I do? I can't change outline renderers in the middle of the outline, can I? And what if I want to use wp text for my page, but put an outline-based list into it?"
No, you can't change renderers in the middle of an outline. The solution lies in the use of an "include" mechanism. Frontier lets you embed the rendering of one Web page inside another.
To see how this works, let's go back to our thirdPage, the one with the list of things to do. Remove the #title and the #renderOutlineWith directives from it; it doesn't need a title, since we're going to embed it in another page, and it doesn't need a #renderOutlineWith directive because we want the default outline renderer.
Now go into secondPage and add, at the end, the following (get it exactly right):
{renderObject (@websites.myFirstSite.thirdPage)}
Now preview secondPage in the browser. Not bad, eh?
The syntax here is {renderObject(@xxx)}, where for "xxx" you substitute the exact full name of the database entry you want to include. Do not forget any of the pieces, especially the "@", or nutty things will happen.
You can perform an Include like this with any kind of Web pages; you can include anything in anything with fairly reasonable results. Clearly you can use this mechanism not only to combine one kind of Web page with another (like putting an outline list into a wp text-based page as above) but also to manage boilerplating.
For instance, you might have a large legal paragraph which you use at various points throughout many of your pages. If that paragraph were embedded at each occurrence with this Include mechanism, then if the paragraph were to change, you wouldn't have to do a find-and-replace; you would just change the database entry representing the paragraph, and render the site anew.
Macro syntax
The syntax of the {renderObject (@xxx)} command, with curly braces, is that of a macro. A macro is just a line of UserTalk. A macro call is rendered by "running" the UserTalk line (that is, evaluating it or obeying it or however you like to envision these things) and replacing the macro call with the result.
For example, if you put {3 + 4} in your Web page, it will be replaced by 7, because "3 + 4" is a valid UserTalk line, and when Frontier "runs" that line, the result is 7.
If you put {user.prefs.name} in your Web page, it will be replaced by your name, because "user.prefs.name" is a valid UserTalk line telling Frontier to fetch the value of the database object user.name.
In the case of {renderObject (@xxx)}, we are using a line of UserTalk which says tells Frontier to find a script called renderObject living in the database and hand it @xxx as a parameter, and run it.
Facts about macros
You can write your own macro scripts once you learn how to program in UserTalk; you can store those scripts anywhere in the database, but there are some commonly used places because of the way Frontier looks for database entries referred to in a macro call.
Here's the rule. If, in a macro call, you refer to something in the database, then Frontier will look first in the tools table in your Web site table, then in user.html.macros, then in html.data.standardMacros (which is where renderObject lives), and finally in the table pointed to by html.data.adrPageTable (this is what makes #define, #defineScript, and custom directives work -- we'll talk about these later). If none of that works, it looks in the database as a whole.
Incidentally, pageheader and pagefooter live in html.data.standardMacros too -- you remember them, they appeared in the default template, and they too were enclosed in curly braces, because they too are scripts being executed through a macro call. Aha, now it all comes clear!
By the way, this means you can't use curly braces in your Web page, because if you do, Frontier will think you mean this as a macro, and will try to interpret what's in the curly braces as a line of UserTalk! Of course, there's a way out; if you need to use curly braces as literals, just put a backslash before the opening (left) curly brace.
Also, Frontier won't see as macros things that are within quotes (literal strings) or angle-brackets (HTML tags): the rendering process figures that such things are sacred, and protects them. (On the other hand, you can turn off this protection by putting a backslash before the first quote or the first (left) angle-bracket.)
What's in the curly braces can be any UserTalk expression. It doesn't have to be a call to execute a script, though it often is. So even if you know just a little UserTalk, you can get Frontier to "calculate" some text without writing a whole script to do it. What time was it when we rendered this page?
This page was rendered at {clock.now()}.
What's 2 times 2?
2 times 2 is {2 * 2}.
Is this making you want to learn UserTalk?
Yes, it's {1 == 1},
I wish I knew {nameOf (root [sizeof (root) - 2])}talk.
|