oowebtools is an open-source TclOO (object-oriented) toolkit for constructing websites. It's designed to facilitate building web pages even if TclOO features aren't used directly. (Naturally extending oowebtools features will probably require deriving classes or using other TclOO capabilities. The majority of users won't need to do this.)
oowebtools is the successor to jwebtools. While the purpose and general patterns of use are similar, the new toolkit leverages the recently completed nxproc extension and represents a thorough revision of old code along with a great many bug fixes. oowebtools has cleaner syntax and greater ease of use.
While oowebtools offers a number of conveniences and ready-to-use components, it works by encapsulating HTML entities making page construction more compact and flexible. Basically the toolkit enables writing page generators. Since these page generators are written in Tcl, templating can be accomplished simply by inserting Tcl procedure calls or variables.
Before getting into details, a brief example of a web page using oowebtools:
proc page0 {} {
Html: --> [subst {
[Head: -title "Example page" \
-descrip "Demonstrates oowebtools" --> [subst {
[Preload: --> {href /js/example.js as script}]
[Preload: --> {href /css/example.css as style}]
[Link: --> {href /css/example.css rel stylesheet
type text/css}]
}]]
[Body: --> [subst {
[H1: --> "Example Web Page"]
[Div: --> {class main} [subst {
[Div: --> {class msgdiv} \
{This is the message.}]
[Div: --> {id imgdiv} [subst {
[Img: --> {src /img/big-country.jpg
alt "Wide open fields"}]
}]]
}]]
}]]
}]
}
The toolkit provides commands corresponding to 42 HTML tags. These are called using a simple syntax:
Tag: <fixed args> <named args> --> {attributes} {text or element list}
Naturally input varies depending on the tag but the pattern is consistent.
In the example, each tag command is called with "-->" followed by one or two lists. The first is a an optional list of attributes. The final (or only list) is either text or list of elements "owned" by the tag. The result is a hierarchical list structure, exactly what HTML is about.
The "page0" command returns the result of running the Html class command. That is, an object itself a command created by "Html:". This object can call the methods defined by Html. The most relevant method is "write". Each tag object knows how to write itself, so when [page0] is called, the web page is written to stdout or possibly another file descriptor.
[page0] write
<!DOCTYPE html>
<html lang="EN-US">
<head>
<title>Example page</title>
<meta name="description"
content="Illustrates using oowebtools">
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<link href="/js/example.js" as="script" rel="preload">
<link href="/css/example.css" as="style" rel="preload">
<link href="/css/example.css" rel="stylesheet"
type="text/css">
</head>
<body>
<h1>
Example Web Page
</h1>
<div class="main">
<div class="msgdiv">
This is the message.
</div>
<div id="imgdiv">
<img src="/img/big-country.jpg"
alt="Wide open fields">
</div>
</div>
</body>
</html>
Here is the complete list of HTML classes in the toolkit. Note that these all have upper case first letter.
A Area Article Audio B Base Bdi Blockquote Body Button Canvas Charset Code Datalist Del Description Details Div Em Embed Fieldset Figcaption Figure Footer Form H1 H2 H3 H4 H5 H6 Head Header Hr Html Iframe Img Input Ins Label Legend Li Link Main Map Meta Meter Nav Ol Optgroup Option P Picture Pre Preload Script ScriptSrc Select Source Span Style Sub Summary Sup Textarea Title U Ul Video Viewport
This doesn't cover all possible HTML tags, but sufficient for most users' purposes. If other tags are needed adding them is pretty straightforward to do.
To use these tag classes, either "Tag:" or "Tag new" works. (These are in fact completely equivalent.) The colon form is more convenient and clearer so usually preferred.
A Article B Bdi Blockquote Body Button Canvas Code Datalist Del Details Div Em Fieldset Figure Figcaption Footer Form H1 H2 H3 H4 H5 H6 Header Iframe Ins Legend Li Main Map Meter Nav Ol Optgroup P Picture Pre Select Span Summary Sub Sup Textarea U Ul
# Syntax
Tag: <options> --> {attrib list} {text-or-element list}
<options>
-nonl (bool 0) "no nl chars around tag"
-zeroindent (bool 0) "no indenting at all"
-indenting (bool 0) "per tag indenting or not"
-indent (int 0) "amount to indent"
-textoutdent (int 0) "move text to left (script,style)"
-leftmarg (int 0) "line starting point"
-fd (str "") "output device"
{attrib list} (str/list)
{text/elements} (str/list of objects)
Methods:
write ?fd? "write" is most useful method, avail in all tags.
Takes one (positional) argument, "fd" or file
descriptor (e.g., from "open"). The default
empty string causes write to return rendered
text associated with the tag.
Area Base Embed Hr Img Input Option
# Syntax
Tag: <options> --> {attrib list}
<options> same as basic tags
{attrib list} $nxargs contains only <attrib value ...> list
Syntax:
Html: <options> --> {<head object> <body object>}
-lang (EN-US)
-fd ("")
Head: <options> --> {elements only - NO ATTRIB}
-title ("") "page title"
-descrip ("") "page description"
Meta: <options>
-name ("")
-content ("")
Link: --> {attributes}
Preload: --> {attributes}
ScriptSrc: -src <URL> ?--> {attributes}?
Script: -outdent <int 0> --> {text}
Style: -outdent <int 1> --> ?{media <value>}? {text}
Label Audio Video Source
Syntax:
Label: -for <str> --> ?{attribs}? {text}
Audio: <options> --> ?{attribs}? {element list}
-src URL
-autoplay BOOL 0
-nocontrols BOOL 0
-loop BOOL 0
-muted BOOL 0
-preload ENUM {auto metadata none}
Video: <options> --> ?{attribs}? {element list}
-src URL
-autoplay BOOL 0
-nocontrols BOOL 0
-loop BOOL 0
-muted BOOL 0
-preload ENUM {auto metadata none}
-poster URL
-width 300 (px)
-height 150 (px)
Source: <options>
-src URL
-type <mime type>
-media "" for <picture>
-sizes "" for <picture>
-srcset "" for <picture>
The toolkit provides a number of object-commands that are not HTML tags but frequently very useful for constructing web pages. These include:
Blist Bsrc Bsrcstub CommentDb CommDiv CommScript CommentRecv Component Contact ContactRecv Dynpage Menu ooWTserv Slider Smtp Srcset WebImg
Several utility classes provide internal support but also have functionality of interest to toolkit users:
Bool Config Log Resource Util Stack
Both groups of commands will be described in later sections.
Element is the abstract parent of all tag classes. Element contains generic functionality used by derived classes, on top of which properties are implemented in addition to or replacing what's defined in Element.
Tag constructors in oowebtools use nxconstructor (from nxproc extension) conferring certain advantages. First, nxconstructor (and nxmethod) allow named arguments of the form "-param value" with each "param" becoming a variable in the procedure body. Also nx- procedures have nxunknown and nxargs variables defined in the body. (By default these variables are empty.) These features are widely exploited in oowebtools.
In nxproc, procedures can have fixed (positional) arguments (optionally with defaults), named arguments, unknown arguments or nxargs.
nxproc mycmd {{fixedarg 100} -namedarg "value" **} { ... }
mycmd 200 -namedarg "text input" unknownarg --> mynxargs ...
In this case, "mycmd" body will have variables "fixedarg", "namedarg", "nxunknown" and "nxargs" containing 200, "text input", "unknownarg", and "mynxargs" respectively. The "twostar" (**
) symbol means input on the command line not matching named arguments will be saved in the "nxunknown" variable rather than causing an error. (Note that "nxconstructor" and "nxmethod" work the same way as nxproc.)
In oowebtools, nxcontructors may have fixed or named arguments. In any case, they make use of "nxargs" by reading $nxargs and either sending data via "next" to the parent class, or processing $nxargs value as attributes and text/list of elements. The latter are saved in instance variables Attributes, Elements/Text which are used by the "write" method as it renders the variables' data into the target web page.
Toolkit users don't need to be too concerned about nxproc details. (Unless intending to use nxproc commands in their own work.)
TclOO classes as commands produce instance objects with create
or new
. As a convenience oowebtools has a namespace Tag
with commands having the names of tag classes plus a trailing colon. Thus Tag::A:
is a command that calls A new
. In practice the Tag namespace exports its command names and these are imported into the tag class files.
The toolkit then works as follows: tag classes are defined in toolkit files. When these files are sourced (via package require oowebtools
) class objects (e.g., Html, etc.) are created. Class objects are commands which in turn create instance objects that are commands in their own right. Instance commands call methods as defined in the class which do the actual work. Here are 4 instance commands calling "write"— all produce the same output:
package require oowebtools
Html create html0 ; html0 write
Html new (-> oo::Obj127) ; oo::Obj127 write
set html0 [Html new] ; $html0 write
set html1 [Html: ] ; $html1 write
If it helps understanding, an instance object/command calling methods is analagous to a namespace ensemble, that is, a command with subcommands. One opinion is the that the class/object structure is easier to organize and more versatile.
Installing oowebtools is simple. It's only necessary to copy the "oowebtools" directory to a location on Tcl package path. A typical location is /usr/local/lib or /usr/lib. Developers often have multiple Tcl binaries in separate directories, each with its own ./lib. In this case, placing a copy of oowebtools in the "lib" directories enables using with the particular versions of Tcl.
The files in directories css, js, db, util will need to be copies to a directory in the target HTML hierarchy whether in development or final versions. Of course in a particular case not everything in these directories will be needed.
The toolkit has these requirements:
These are available from the following sources:
Obtaining/installing these dependencies is straighforward and mostly painless. Once accomplished install oowebtools per above.
Description of class object constructors. HTML tag class constructors are written using nxconstructor from the nxproc package. These constructors use the same basic patterns to initialize object instances. The basic syntax is generic:
<Tagname>(:| new) ?positional_args? \
?-option ?value? ...? --> \
?{attribute value...}? ?{text|element list}?
Tagname always starts with an upper case letter, followed by ' new' or its abbreviation, a colon.
There can be 0 or more positional/fixed args. Those without default values require a value entered on the command line.
There can be 0 or more named args. These are entered on the command line as ''-option value'' except for boolean types—the option alone toggles the default value. In most cases named arguments are attributes to be appended to the Attribute list for the entity.
Most tags classes are further configured by the ''end of argument'' symbol, -->
, followed by one or two lists, an attribute list and/or a text string or list of tag objects.
An attribute list looks like {class main id main ...}
. Element lists can be generated by using [list ...]
, or [subst {...}]
. The latter is often less confusing so that style is recommended. In any case everything following -->
, is collected in the nxargs
variable. nxargs
is used in the next
command to pass info to the superclass constructor.
next ... --> {*}$nxargs
Element has several named args, including the all-important -tag
and -endtag
.
next -tag div -endtag 1 --> {*}$nxargs
nxcontructor defines another args-like variable, nxunknown
which collects anything on the command line (before -->
) not previously defined. It is also passed to the superclass constructor.
next -tag div -endtag 1 {*}$nxunknown --> {*}$nxargs
If the tag constructor has named arguments for configuring attributes, the associated variable are used after the next command.
nxconstructor {-class "" -id ""} {
my variable Attributes
...
next ...
lappend Attributes class $class id $id
}
Naturally there are variations on the above. Questions are ultimately resolved by the source code for a particular class.
When oowebtools is loaded all files are source
'd which creates a class object for each toolkit entity. Class objects are used to create instance objects which call methods to render expected HTML output.
The syntax of Element-derived classes was described above.
This section attempts to describe the syntax of composite class objects not derived (or partially derived) from Element.
To be completed…