Using an interpreter-safe version of MIT's Object Tcl, The Otcl NeoWebScript Interface brings object orientation to the NeoWebScript page developer. This interface allows the user to define classes for generating blocks of hypertext in Tcl, including tables and forms. An extensive "query" class has been created to interface to a Postgres95 database backend.
I would like to mention some of the shortcomings up front. Mainly, NeoWebScript does not yet have a good way to set up libraries of useful code, ala the Tcl autoloading feature. Release 1.0 contains some initial efforts I made at it, but it will probably change a lot in future releases. Ideally, one would like to to establish a directory somewhere for general library routines, including class definitions. The user should only have to reference a Tcl procedure or invoke a class (by creating an instance), and would not need to know where it is defined. Until then, fairly general code is found in one of the *.tcl files found under the httpd/conf directory.
Currently, specialized class code is loaded using load_file
. The
only exception to this is the "using_otcl" command. This is called by
the user when they want to invoke Otcl commands, and by also loads
in class.tcl which is found under httpd/conf. The classes documented
here can all be found in class.tcl.
In using the pre-defined classes given here, the user should think of defining the objects as the setup phase for the application. The actual work (and thus time) then used to make the queries, display the data, and pass information to and from the database.
Tk programmers will find the interface vaguely familiar, as items
are declared with dot-separated pathnames which generally
determine how hypertext objects are grouped together. Any object which
implements the display method, must cause the object to return the HTML
code which is represented by the data contained therein. display
may be sent directly to an individual object, or it may be sent to
a higher level object. It is up to the class defintion to call
display
for any subordinate objects. Note that the order
of object creation will determine the traversal. Individual objects
may support the enabled flag, and may consequently be disabled
(object-name enabled 0
). Objects are
traversed and displayed in the order they are created.
Some objects are context-sensitive. For example, an input object
(eg. a select box or text input field) can be used anywhere, but if these
objects are not displayed within a form, then they merely output
plain text.
For example, consider the following code fragment:
form f input f.fred -type selectbox \ -text {a line for fred} \ -name fred -size 10 input f.dave -type text -text \ {a line for dave} html [f display]
The form object f is created, which contains two members,
f.fred and f.dave. The HTML returned by the call
to [f display]
resulting from the above code is an HTML form
containing input field declarations with default text given above,
as follows:
If no text value is declared for a form element, it is assumed that the form will be associated with query object (-query) and that this object contains either the results of a POST, or an SQL query. In either case the names of the response or the attributes of the query (must) correspond to the names of the input fields.
The last step in generating HTML for a form (or hypertext) object is to call the query method subst to substitute the actual values in the query object.
This is done in two phases because it makes implementation of the relationship of hypertext to a query more flexible. Any object which is asked to display itself will call the subst method if a query object has been associated with it (-query objectname). An object's display method may delay final substitution by emitting tcl code surrounded with brackets. The select input object uses this to make the correct item selected when an input item has been read from a query.
Generate HTML for this object. f and t both default to zero. A non-zero value means that the HTML is being generated within a form and/or a table, respectively. If within a form, then objects can generate HTML for inputting data, otherwise they generate text. If an object is emitting data within a table, then it should emit <td></td> around it's output.
The user of display is responsible for the actual output. For
example, common usage would be
to send the output to the browser. The individual
object output a table, regardless whether it is already inside one,
ie. nested tables can easily be done.
html [myobject display]
Both the response and query classes accept this method. The response is loaded into the object from a POST or QUERY.
Defaults to true, and is used to disable the display of an object by setting it to 0 (false).
Not to be too confusing, a query option defines the name of the query object to be used with this object.
The name of a Postgres95 relation to be used when generating some SQL queries.
The name of an object defaults to the last component of the dot-separated pathname of the object. When input items are generated, the name will be used in the NAME= parameter when display generates HTML.
If using Postgres95, then the name must also equal the Postgres95 field names in order for -query substitutions to work correctly.
Nearly all objects will accept a -text. Setting -text implies -isattr 0.
If -prefix is accepted, its value will be emitted by the display method before the regular text. This makes it easy to generate forms with labeled items. Prefix is not emitted if the output is a table.
A specialized class exists for defining "direct attribute options." These are options that are used by various objects, but are not interpreted by them. They are a one-to-one mapping to HTML options. The following are supported by some of the objects below.
The using_otcl
command is used to install the otcl commands
and class.tcl code into the safe interpreter. This command must be
executed before any of other pre-defined class commands.
General mechanism for grouping together hypertext.
<A HREF="$href">[text and member text]</A>
If -text was configured, it appears first. Then <FORM ...>. Each member object is called to display their contents. Display is called with arguments 1, which should be interpreted by the member object that it is within a form.
If -table is specified, then the table will be called to display itself before the form's own members are called. The table will format up nicely, and the form's members can be used for things like "Update" and "Add" buttons (or whatever).
If -name is not specified, then it defaults to last component of the object's dot-separated name.
If the text is not specified, then it is assumed that the -name value (or the default) corresponds to a variable within a query object. In this case, the value of text is set to $(the value of -name), which will invoke a substitution via the query subst method.
Return proper <select></select> and <option></option> pairs. If the value is found in the selected list, then the items is properly selected. If an attribute(query) value is present, then it is used instead of the explicitly selected value.
Set the value of the selected option. This will be the displayed option when the select box is generated, unless a query is connected, in which case the query overrides the selected value.
Set the value of the options to be available. value is the name that is posted by the browser if the item is selected. If text is not given, then it will default to value.
This is a short-cut method for setting all of the options in one command. You must supply a proper Tcl list. Each element of the list must itself be a list of value-text pairs which define all of the options available. All previous options are discarded.
Edit_input: An abstract class which supports the delete_check, edit_button, and update_button classes. Each of these must have a -relname argument in order to generate the proper HTML from an SQL query. If not displayed within a form, display emits no HTML at all.
The goal of all of these is to be able to easily mass-edit the results of an SQL query. The following subclasses are defined:
Generates HTML which uniquely identifies a Postgres95 tuple to be deleted. If the checkbutton is depressed when submit is hit, information will be passed which can be processed by the query class into SQL delete statements.
Generates HTML which, when posted, allows the receiving URL to identify a Postgres95 tuple, presumably to be displayed and edited.
Works closely with edit_button to submit a form that has been filled out by the user. Specifically, it includes in the posting the Postgres object identifier (oid) and relname of the tuple being updated.
This class is a subclass of form. The single added behavior is that a hidden type is automatically generated within the form for called 'oid' (or that given by -oidname). An attribute of this name must be returned by SQL queries. This value and the relation name are used to uniquely identify a record to updated.
Returns a list of attributes which match the glob-style pattern.
The sqlquery class must be a child path to an sqldb object. It's instance variables all start with _, so that database tuples can easily be stored without fear of conflict.
Instance variables:
Set the _index to $i.
Any previous query results are cleared. Then execute the query. set _result, _attributes, and _numtup. Resets _isresponse to 0. The return result is a 1 if sucessful, 0 otherwise.
Loads the $i'th tuple. Attribute names become Otcl instance variables, their values being extracted from the query. Sets _index to $i.
One per line, the values of all the variables in query are dumped to html.
The input text is passed to the tcl subst command after the current attribute/instance variables have been brought in. This has the affect of replacing any tcl command or variable variable references within 'text' with their value from a query or a post.
The current response variables are loaded into the query object. Usually this is in prepartion for an sqlupdate.
attrname must be the name of an attribute that is defined in the object. It's value is used to generate an SQL 'select' command. If a record is found, calls 'setvars 0' on itself. Returns 1 if successful. Requires relname be set for this object.
The current query object attributes are updated into the sql database. If the attlist is supplied, only those variables are set within $_relname. Returns 1 if successful. If no response is currently loaded, or an error occurs, 0. This method keys off of special response values matching the pattern __UPDATE, which are generated by special update_button object.
The current query object attributes are inserted into the sql database as a new record. If the attlist is supplied, only those variables are set within $_relname. If no response is currently loaded, or an error occurs, returns 0, else 1.
Key is the name of an attribute which selects this record. An update set query is generated to set the database to the values present within this instance. Returns standard exec response.
The current query object matching the oid in the database is deleted.
The current query object attributes are updated into the sql database. If the attlist is supplied, only those variables are set within relname. If no response is currently loaded, or an error occurs, returns 0, else 1. A special response coded as __DELETE/relname/oid determines which records are deleted. This is generated by the object delete_check.
Manually install attname with value value into the object. This is useful for, for example, setting transaction dates to the current time, or preparing for a lookup.
Generate a table. Attribute names are used in the first row of output to produce a heading. Underscores are replaced by spaces. For this reason only, you may want to use uppercase letters in your attribute names. If -rowhtml was specified, then the given object is used to generate each line of the table instead of the default, automatically generated one.
Instance variables:
The defaults class contains attribute value pairs, and may be used in place of a query. The default object will substitute empty strings for undefined attributes. This object allows a form to be filled in with whatever values you choose, vs. filling a form in from a POST or an SQL query.
Methods:
Notes: think of this as a manually setup response or query object.
Randy Kunkee
kunkee@neosoft.com