Fixing Frontier Five

  Locations of visitors to this page
be notified of website changes? subscribe
lawyers!

 

Frontier

Using Frontier

Extending Frontier

adding favicons

migrating websites

Using CSS

Fixing Radio 8.1

Fixing Frontier 5

nextPrev broken

err log sans timestamp

temperature conversion

our WebRing

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Fixing Frontier Five

Userland Frontier is a very powerful tool with which to render web sites - one of the best - but its concept of modularity is fatally flawed in my opinion and puts an unreasonable - and probably unanticipated - burden on the webmasters who use it. While trying to determine whether I understood the problem - and hoping that someone else had already solved it - I searched through the discussion archives of the Frontier programming community and spoke with some if its better-known participants. I conclude that the problem is neither understood nor solved. Here is an explanation and a solution.

(This isn't an introduction to using Userland Frontier to manage web sites, although I believe that new webmasters will find the technique described herein to be a great time-saver. After all, If you're anything like me you'd rather spend time on content, not maintenance.)

The problem

one big website

Let's start by taking inventory of a typical website as it appears in Frontier. OneBigWebsite has a #template, an images table, and two sub-directories of content.

When we render a page, say the Eating page, the Frontier engine starts at the directory in which the page resides and looks for a #template from which to take its look and feel. When it can't find it in the food table it "bubbles up" one level to the OneBigWebsite table and performs the same search. This time it finds the #template, and through a sort of programmatic guilt by association, the images table. Now it can render the Eating page, pouring its content through the structure of the #template, taking graphics from the images table.

The #template serves two purposes. It's overt purpose is to direct the look and feel of all the pages in the web site. Its second purpose is to serve as an anchor, to tell Frontier's rendering engine the location of the images table.

OneBigWebsite has all its images in one table, making it impossible to move any of the subtables independently of the others. We want to make each topic be self-contained. First we create an images table in each topic table. Then we move the graphics from the top-level images table to the appropriate topic images table. Now we're almost self-contained, but it's with the final step that we'll run smack dab into the problem with which I've been wrestling.

discrete weblets

The images have been moved, but now we have to alert the rendering engine as to which images table to use. We do this by placing a #template entry at the same level as the images table. But what #template do we use? If we want each "weblet" to have a different look and feel then it makes sense to have individual #template entries. But let's assume a simpler case: we like the look and feel we've designed for the site so we move a copy of #template into each topic table.

So far so good. Now the pages and their images are in a single movable subtable with their own #template so the Frontier rendering engine knows which images table to use. Truly modular. But not all is quiet on the rendering front.

The next day we decide to change some aspect of the site's look and feel. In a perfect world we'd only have to change the top-level #template. But we now have two copies of the #template so we're forced to find and change each of the #template instances. This is a time-consuming and error-prone task (especially if your site is bigger than two weblets), and one that should be completely unnecessary in a Frontier universe.

The problem in a nutshell, then, is this: Frontier overloads the #template with two meanings when it should have used the #template only for its content and added something like a #weblet directive to stop the rendering engine from bubbling up the hierarchy too far.

Let me add one more wrinkle to the problem before I present you with a solution.

Let's say I want the same look and feel throughout some or all of a website, but some weblets should have additional content. But I don't want to have to edit each #template to include the content. My interests as webmaster are best served if all my #template instances are simple and identical.

If only I could use a single intelligent, context-sensitive #template, one that would let me keep all the common elements in one location and show local elements as appropriate. After some coding, I can, and so can you.

The solution

Let's start on the path to a solution by looking at the completed results. The body of the web page appears in a tan area, the horizontal rule page separator appears in green, the navigation links in blue, the site credits in yellow, and the optional local elements (in this case an advertisement and an announcement of membership in a webring) appears in salmon. (Notice please that the Geeking page shows a webring membership announcement while the Eating page doesn't.)

rendered-pages

How did I generate these pages without duplicating information in each weblet? I'll answer that by showing you the DiscreteWeblets hierarchy, the common #template, and the UserTalk functions I wrote. (DISCLAIMER: what you're about to see are the first results of my quest and are not polished code. I expect that proper coders of UserTalk will take me to task for not having done something properly. I'll publish improvements in a follow-up.)

Here's the generic #template that gives us both a look and feel and acts like an anchor, but that doesn't require us to find and edit it when we change some common element.

template

My generic #template starts by generating a pageheader and writing the title passed to us on the page in a font size of plus two. Then it emits the bodytext passed to us. Then we start the footer by switching to a smaller font, centering everything that's to follow, and drawing a horizontal rule across the page. Then the interesting stuff happens.

Next comes two examples of content common to the entire website, content that exists in one place and used by each page in the site: the Site Credits and the Navigation Links. The former is a WP Text, the latter a UserTalk script. I'm using one of each to prove it can be done. (Use each type to its best advantage.) I use the WP Text for simple content that doesn't require computation (although it is processed for macros - you'll see how a call to clock.now is evaluated). I use the UserTalk script for content that requires computation (in this case to generate navigation links to all pages but the one being rendered).

The comes two examples of content local to each weblet, content that exists in one place in each weblet and is shared by each weblet pages: the webring membership announcement and SOMETHING. MIRROR PREVIOUS PARAGRAPH.

WP Text common to all web pages

The Site Credits are contained in #siteCredits:

sitecredits

The #template line

{renderObject(@adrSiteRootTable^.["#siteCredits"])}

calls the Frontier function system.verbs.builtins.html.data.standardMacros.renderObject, passing it @adrSiteRootTable^.["#siteCredits"]). Translation: "please render the object #siteCredits which you'll find at the top of this site". (I don't know exactly how Frontier knows where the top of the site is, perhaps where the #ftpSite table is located.)

Frontier evaluates contents of #siteCredits as part of the rendering process, finding and processing UserTalk macros. The call to clock.now() is recognized as UserTalk because of the enclosing braces, is evaluated, and the result is inserted in the text stream.

We've now abstracted the site credits away from each of the #template copies into a central, common location. If we want to add a copyright notice to the site credits we need only edit the single instance of #siteCredits. Pages rendered after we make the change will automatically pick up the new site credits. No more hunting down and changing each #template in my web hierarchy.

UserTalk script common to all web pages

That was easy. We just included a common bit of text into a web page. That text even had a UserTalk macro which was evaluated. This is powerful stuff. What if we want more computing power at our beck and call? Let's see how to invoke a UserTalk script, a complete program in its own right. The #template line

<center>{navigationLinks()}</center><p>

centers the output of my home-grown function navigationLinks, shown here:

navigationLinks()

It's a deceptively simple function. It defines a local variable, s, and a local function, linkThis. linkThis checks to see whether the first argument passed to it, glossaryEntry, is the same as the title of the page currently being rendered. If so, it uses the second argument passed to it - a readable form of this title - as a simple text string. Otherwise it uses Frontier's glossSub function to generate an URL to the page and uses readable form as the hyperlink text.

navigationLinks calls linkThis twice, once for a page with a title of "Eating" and again for a page with the title of \"Geeking". I put a vertical bar surrounded by two non-breaking spaces inbetween to make the navigational elements easier to read.

Now we've abstracted a UserTalk script away from the #template and into a central, common location. Change the script and the new output will automatically be used by any #template copy that invokes the script. Add a weblet to the site and you need only change the navigationLinks function in #tools (instead of finding and changing a function defined in each #template, a programming technique not discussed here).

WP Text local to each weblet

So far so good. We've abstracted two chunks of content out of the #template and into a central, common location. The #template is now simpler and doesn't require that we edit it to change site-wide content. Now let's turn our attention to content that varies for each weblet.

Some of my pages are members of a webring, a list of pages devoted to a particular topic. For the purpose of demonstrating the inclusion of optional local content I'll assert that webring membership is either true or false on a per-weblet basis, not a per-page basis. Of course, I want the announcement of webring membership to happen without editing either #template.

The line

{localContent(@adrObject^, "#webRing")}

calls my home-grown function localContent with two arguments. The first specifies where to start in the Frontier database hierarchy, the second specifies the table name for which the function should be looking. @adrObject^ is Frontier shorthand for the page being rendered, #webRing is a name I made up to denote any information about webring membership. localContent is shown here:

localContent()

Another of my home-grown functions, localRoot, is called by localContent. localRoot is shown here:

localRoot()

localRoot is given a place to start in Frontier's database hierarchy, and it bubbles upwards until either it reaches to top of the hierarchy (in which case it returns an empty string) or it encounters a #template (at which time it returns the address of the table which contains the #template). localContent uses that information to search for an instance of #webRing next to the #template.

You, of course, can create any local content and give it any name you wish. localContent will find it. You may also have several different kinds of local content. Call localContent once per category. Perhaps a #goodCause entry will have a plea for monies for the Tibetian government in exile in one table and an reminder to have pets spayed in another.

My #webRing consists of one line:

This pages is part of the Geek WebRing

UserTalk macros would be evaluated in this context as well. In a real-world example I'd include double-quote the webring name so Frontier would replace that with a link to an explanatory page about that webring.

UserTalk script local to each weblet

TO BE ADDED

system.verbs.builtins.html.buildPageTable

system.verbs.builtins.html.buildPageTable

Matt Neuburg

Conclusion

I've shown you how to abstract various types of content out of the #template copies you're forced to keep around your Frontier web hierarchy (to inform the rendering engine as to which #images table to use). With these techniques you can design a master look and feel to your site, including various instances of common content (like the navigation bar in this example) and local content (like the particulars of webring membership), and then generate one #template that may be copied into each topic weblet. The common content need only be changed in one location, and the local content will be used as appropriate to each weblet.

One less item of maintenance, and more time you have for creating content.

This demonstration was coded and tested on an Apple Macintosh PowerBook running MacOS 8.1. My programming tools were Userland Frontier 5.0.2b20 with root upgrade 114, Microsoft Internet Explorer 4.01.

geeking-index

firstfilter

eating-index

copyright

advertisment

This page is part of the Userland Frontier WebRing. webring List all this webring's pages; visit another page; add your page to this webring.

Have you found errors nontrivial or marginal, factual, analytical and illogical, arithmetical, temporal, or even typographical? Please let me know; drop me email. Thanks!
 

What's New?  •  Search this Site  •  Website Map
Travel  •  Burning Man  •  San Francisco
Kilts! Kilts! Kilts!  •  Macintosh  •  Technology  •  CU-SeeMe
This page is copyrighted 1993-2008 by Lila, Isaac, Rose, and Mickey Sattler. All rights reserved.