Tutorial: Building a Small Site
![]() |
![]() The Document Assembly Tool |
|||
Tutorial: Building a Small SiteIn this section you will find a ready-made website with two pages to get you started. Most importantly, everything is carefully documented with running commentary to really help you put the whole thing together. We strongly encourage you to work carefully through this tutorial as you read it: it will give you significantly better insights than if you were merely to scan it and even skip about. Take our word for it: Learn by doing! Getting Started
Let's include the pre-packaged utility files. WebLord will look for these in the current directory. Since these filenames have no directory and/or volume symbols, WebLord will, if not found in the current directory, look for them in the ~/weblord/ directory, and next in the /opt/share/weblord/ directory. If found in none of these spots, WebLord will complain about the lack of the file and stop. #include "html.wl" #requires-version 2.0 N.B. The HTML.wl file is already provided to give you exactly this. When you want to build an HTML file you can simply include the HTML.wl file and it will include all other files for you. As you've noticed I sort of like tables because they give me a lot of control over placement of specific things on the page without compromising the markup ideas of HTML. Let us create a page layout using tables: text page-pattern { value = '<table cellpadding=8 width="100%" align=left>\n' "<tr>" table-logo-area table-heading-area "</tr>\n" "<tr>" table-navigation body "</tr>\n" "<tr>" table-about-area table-footnote-area "</tr>\n" "</table>\n" } The table above has three rows ( text page-pattern { value = '<table cellpadding=8 width="100%" align=left>\n' "<tr>" table-heading-area table-logo-area "</tr>\n" "<tr>" body table-navigation "</tr>\n" "<tr>" table-footnote-area table-about-area "</tr>\n" "</table>\n" } Ok, that seems easy enough, but try that with a finished page. And then decide that the result sucks and undo the work (but you would have made a backup first, right? Good for you! :-) But what this demonstrates is that we merely had to move the references for the objects, not make any major changes. This starts to hint at what WebLord can do for you. Just wait, this is only the proverbial tip of the proverbial iceberg! Let's use the first version of the table (for tradition's sake) and define each of the six cell elements, table-logo-area, table-navigation, table-about-area, table-heading-area, body, and table-footnote-area: table-logo-areaThe "table-logo-area" object defines the contents of the upper left cell where you can often find the company or product logo: text table-logo-area { value = '<td valign=top width="140">' product-logo '</td>' } And the "product-logo" is defined this way: text product-logo { value = »<img src="product-logo.png" width="140" height="48" alt="Logo">« } There's something weird in the product-logo, isn't there? What's with these » and « symbols?! Well, you don't have to use these symbols, but they function as a pair of quotes just like the " and ' symbols. If you have lots of ' and " symbols in a string, you would ordinarily have to escape the meaning of an embedded quote by preceding it with a \ symbol (as with a \" or \' sequence); the »...« sequence is simply another option. But now, back to the "product-logo"... Let's convert this from a simple Text Object to one that may provide us with more flexibility later on: We'll highlight the important changes: text product-logo { value = html-image; image-src = "product-logo.png"; image-width = "140"; image-height = "48"; image-alt = "Logo"; } Does this look more complicated or simpler? Well, it depends on how you look at it. If you use a lot of images on your page (perhaps you have created dozens of navigation buttons, all the same size) then you might want to use a global image-width and image-height and leave out these items because the global values will be inherited. What would this look like? site main { image-width = "140"; image-height = "48"; } text nav-button-1 { value=html-image; image-src="nav1.png"; image-alt="Products" } text nav-button-2 { value=html-image; image-src="nav2.png"; image-alt="Support" } text nav-button-3 { value=html-image; image-src="nav3.png"; image-alt="Email Us" } text nav-button-4 { value=html-image; image-src="nav4.png"; image-alt="FAQ" } Do you see how quickly we just defined four buttons, all the same size (140×48 pixels), without having to duplicate the width and height over and over again? This demonstrates one of WebLord's central concepts: inheritance. The width and the height of the images is inherited. Inherited from where you ask? Excellent question!! Let's take this opportunity to briefly explain what happens when WebLord reads a site description:
Additional SITE objects are ignored. Anything defined by the Site Object is inherited by each of the pages, unless the page defines a property of the same name and thus overrides the inheritance. Likewise, any object that a page references will inherit everything that the page defines (or inherits). And again, whatever this object references, it will inherit whatever its parent object inherited. So if two objects A and B each references object X and object X makes use of a property that it doesn't define, then either A or B provide this value, depending on which of the two is currently referencing X. If this value differs between A and B, then X sees a different value depending which object, A or B, referenced it. X is said to be polymorphic. You don't need to remember these terms, though you can impress your friends by throwing them into the middle of a conversation. Try this one: "The polymorphic nature of WebLord objects is made possible through fully dynamic inheritance." It will leave them speechless! But back to our original discussion on creating contents for the six cells that constitute our pages. I believe we've pretty much covered the little logo in the upper left corner. Let us now examine the navigation bar: table-navigationThe navigation bar usually has a bunch of nice images, text, or both. Let's create a simple navigation bar first, and then go on to a more flexible one: text table-navigation { value = '<td width="140" align="top">' nav-buttons '</td>'; } text nav-buttons { value = nav-button-1 "<br>" nav-button-2 "<br>" nav-button-3 "<br>" nav-button-4 } Remember the discussion about images we had above? Those four objects are the buttons we now use. Alas, these are merely images, not actual links to take us to another page. But don't despair! Add a link property to each image. The new image definitions (starting with what we had defined earlier) become: text nav-button-1 { value=html-image; image-src="nav1.png"; alt="Products"; link="products.html" } text nav-button-2 { value=html-image; image-src="nav2.png"; alt="Support"; link="support.html" } text nav-button-3 { value=html-image; image-src="nav3.png"; alt="Email Us"; link="email.html" } text nav-button-4 { value=html-image; image-src="nav4.png"; alt="FAQ"; link="faq.html" } WebLord magically does the rest! That's all quite nice, you say, but I don't want to define a different navigation bar for each page. I.e. the "nav-buttons" object above would suffice for one page, but the next might not have "nav-button-1" on it, so I'd have to define a new button bar. That's a pain! True. The easiest way might be to define a new button bar for each page, and it's not like that's so difficult. But there is a solution to your pain! This solution gets into some complex stuff, however. You might want skip this section if you are not inclined to delve too deeply at this time. A flexible navigation barWithout meaning to jump too far ahead, it is necessary to mention that the following relies on an (inherited) property named "page-name" which is defined differently for each page. You can choose a different property name, of course, but you'd have to ensure that you make the appropriate changes below and on your pages. Consider this: page Support { value = header page-pattern footer; } text nav-buttons { value = nav-products nav-support nav-email nav-faq; } text nav-products { if=page.objectname "!=" "products"; then=nav-button-1 "<br>" } text nav-support { if=page.objectname "!=" "support"; then=nav-button-2 "<br>" } text nav-email { if=page.objectname "!=" "email"; then=nav-button-3 "<br>" } text nav-faq { if=page.objectname "!=" "faq"; then=nav-button-4 "<br>" } There is a lot more going on here, though it might look relatively simple at first. To begin with, the "nav-buttons" object has the usual "value" property with four object references. These references, however, do not simply define a "value" property. Instead, they have an odd combination of "if" and "then" properties. You have just encountered conditional objects! Just like the "value" property, the "if" and "then" properties are built-in. This is what happens:
Exactly how an object's value is determined requires an understanding of the following factors:
QUIZ #1: Support for the "select-case" property was added with WebLord 1.1. What would WebLord 1.0 do with an object that uses a "select-case"? Click here for the answer. But back to our flexible navigation bar. What exactly is happening there? First of all, the "nav-buttons" object references all navigation buttons, but not directly. Each of these indirect references uses a condition. The first button ("nav-button-1") is only included if the (inherited) property "page.objectname" is not equal to "products". If this navigation bar is referenced while the page "Products" is being built, then the "nav-products" will evaluate to "" (nothing), wherefore this button will not appear on the page (but the others do.) This kind of navigation bar will work for a relatively small site, a dozen pages or so. In the long run, however, it may be easier to define and manage a site if each page simply had a property "nav-buttons" that listed the buttons to be used (as in "nav-button-1 '<br>' nav-button-4") and you wouldn't define an object named "nav-buttons" at all. table-about-areaThis area might just be another button, or it might be left blank. We won't concern ourselves with it because our demonstration site will put nothing of significance there. If the table-about-area is undefined, it will simply remain empty. table-heading-areaWe will use this area of the page to display the big page title (and maybe a subtitle). Before we go on, however, it becomes valuable to talk about PAGE objects. As mentioned above, all specifically (or implicitly) named pages for a site are generated one at a time. The contents of a page are built from the "value" property that the page defines. In this way, a Page Object is deceptively similar to a Text Object. Page objects do not recognize conditionals, however. If you define a "select-case" or an "if" property for a Page Object, these will be ignored without effect: The Page Object defines properties different from the Text Object. At the very beginning we included three files: html-page.wl, tools.wl, and html-image.wl; The html-page.wl file defines convenient "header" and "footer" objects for the HTML page. Referencing these (provided no "header" and/or "footer" properties are defined or inherited) provides you with a simple, yet highly effective means of building the framework of an HTML page. page products { value = header page-pattern footer; } The above defines a Page Object whose value (contents) is the value of the "header" object, followed by the "page-pattern" property (or value of an object by that name), followed by the "footer" object. When we first launched into this commentary, we began with a Text Object by the name of "page-pattern". Do you see how this whole thing is beginning to come together? The "page-pattern" referenced here makes various references, among which is "body" and "table-footnote-area". For the page title, we'll define the "table-heading-area" property thus: text table-heading-area { ifdef = title; value = "<td valign=top><h1 align=center>" title "</h1>" "<hr></td>"; } If the "title" property is defined for this page, then this object produces a (centered) heading and a horizontal rule (HR) beneath it. bodyThe definition for the page begins to take shape based on these requirements: page products { value = header page-pattern footer; page-name = "products"; body = "This is the contents of page 1. " "Easy, don't you think?"; title = "The Products Page"; } Notice that the "body" property consists of two (quoted) constant strings. WebLord will simply concatenate everything. Quoted text is taken as-is. Unquoted names are evaluated as property or object references. Everything is strung together in the end. It is now clear that "page-pattern" is a polymorphic object. It "changes" depending on which page references it. In fact, the "header" object is a polymorphic object, too. It makes use of a whole bunch of inherited properties, combining them into a properer HTML 3.2 compliant header. I'll leave it to you to look through the html-page.wl file, but here is yet another version of the "products" Page Object with properties added that the "header" reference in the Page Object's "value" property will use. page products { value = header page-pattern footer; page-name = "products"; body = "This is the contents of page 1. " "Easy, don't you think?"; title = "The Products Page"; # also used by "header" description = "Product and price listings with ordering information"; keywords = "mordorsoft sloth widgets product price ordering"; author = "J.Hendrix"; nav-buttons = nav-button-2 "<br>" nav-button-3 "<br>" nav-button-4; } At the beginning, of course, I promised you two pages. It would be cheating, of course, if I merely copied the "products" page and changed a few things. Instead, we'll make this a dynamic page! Consider this: page faq { value = heeader page-pattern footer; page-name = "faq"; body = faq-body; title = "Frequently Asked/Answered Questions"; description = "This page is needed because too few people RTFM..."; nav-buttons = nav-button-1 "<br>" nav-button-2 "<br>" nav-button-3; } What's different? The "body" property, of course. It references a "faq-body" object (or property.) Let's define this object: text faq-body { value = "temp.file"; exec = "Work:www-tools/build-faq >" value; exec-cleanup = "c:delete " value; value-type = "varfile"; } You're probably a bit confused now, aren't you? At first glance, it would appear that the "faq-body" object simply has a value of "temp.file", right? Yes, but only at first glance! The meaning of the "value" property is changed, however, by the presence of the "value-type" property. The object's value, therefore is actually the contents of the file named by the "value" property. But things don't end there!! The exec property first executes the command that it defines. In this case this works out to the command Work:www-tools/build-faq >temp.file This actually executes a command (build-faq in the "Work:www-tools/" directory) and redirects the output to the file named by the object's "value" property. After that has happened, the contents of the file is read to become the value of the "faq-body" object. And then the exec-cleanup command is executed to perform a cleanup operation (delete the temporary file.) But wait, there is more! The "value-type" property indicates that the value from the file contains special sequences of characters beginning with ${ and ending with the } symbol. The text between these is... a property or object reference!! Naturally, you could leave off the exec and exec-cleanup portions in this "faq-body" object. The value of the object would then always come from the file named in the "value" property. table-footnote-areaWe'll leave it to you to define or leave blank the "table-footnote-area" property. You should have enough material at this point to come up with something, even if it is little more than a (small font) version of the (hint hint!) "table-heading-area"... Answers to QuizzesAnswer to Quiz #1: WebLord 1.0 would ignore the "select-case" property, skipping to the next step in the list and expecting to find a "value" (or "image-url") property. Finding none, it would complain. There are more subtle problems that can stem from using older versions of WebLord with files that rely on newer features. For this reason, the requires-version command in every file should indicate the minimum version of WebLord that can successfully process the file! |
||||
This material is Copyright © 1997,1998,1999,2000,2001 RingLord Technologies and Udo Schuermann. All rights reserved. The latest versions of the WebLord software and (this) documentation can be obtained from the WebLord Home Page (the link will only function if you are connected to the internet.) |