This class privides HTML page generating methods for VIP applications. The code in VipStyle.pm as distributed with the VIP base package should be considered as a starting point to generate your own design. At least methods logo and page_footer should be customised for a real application.

Page layout consisting of six parts like header, status (see below). VipStyle contains methods to configure this parts and methods to generate HTML tables and some other HTML elements.

Each page consists of six parts:

  |                  Logo                    |
  | Validation |  Status                     |
  | Navigation |  Content                    |
  | Tree       |                             |
  |            |                             |
  |                Footer                    |
This could be a picture.

Validation Action
This is a Link. Login when the surfer is not yet validated; Logout when he is validated or Restart after a logout when his session was deleted.

This field displays the most important status message, which are - in descending priority order as follows:
Navigation Tree
This field displays a tree of links to features of your applications. Only one branch of the tree may be expanded. The currently executing feature is highlighted.

This is the page content, generated by the scripts. While all other fields are mostly under the control of VipStyle.pm, the content is generated by your scripts.

The footer is used for information about when and by which application/script the page was generated. A contact address would also be nice here.


 #!/usr/bin/perl -w
 use strict;
 use vars qw($cgi, $style);
 use CGIsession;
 use VipStyle;
 $cgi = CGIsession->connect();
 $style = VipStyle->new( -cgi=>$cgi );
 &handle_request() unless $cgi->request_is_redirected();
 sub handle_request {
     if ($cgi->param('go')) {
         my $mail_to = $cgi->param('mail_to');
         if ($mail_to ne 'gerber@id.ethz.ch') {
             $style->error_msg('Mail only to gerber@id.ethz.ch allowed.');
             $style->focus('mail_to'); # the first focus will hold
         } elsif (length($body) > 100) {
             $style->error_msg('Your message is too long; ' .
                               'please send me only short messages!');
             $style->focus('body');    # the first focus will hold
         } else {
             # send the mail
             $style->success_msg("Mail send to $mail_to");
             print $cgi->redirect('an_other_script.cgi');
 sub print_form {
     $style->focus('mail_to');  # default for a page without error messages
     $style->navigation( -highlight=>'home', -expand=>'home' );
     print $style->page_header();
     # -- start of content part:
     print $cgi->startform;
     print $cgi->textfield(-name=>'mail_to'), $cgi->br;
     print $cgi->textarea(-name=>'body', ...), $cgi->br;
     print $cgi->protected_submit(-name=>'go', -value=>'Sendmail');
     print $cgi->endform;
     # -- end of content part:
     print $style->page_footer;


VipStyle methods never write anything to standard output. Your scripts must print the results of method calls like page_header and page_footer.

Object Constructor

$style = VipStyle->new( -cgi=>$cgi )
The constructor needs a reference to the CGIsession object.

Page Header and Footer

print $style->page_header( ... )
The page_header method returns HTTP-headers, HTML-headers and the logo, validation action, status and navigation parts of your page; and starts the content part by writing its title. All this is returned as a string. For best results, your scripts should print it to STDOUT.


-title => $html_title
Optional. Defines the <title> in the HTML <head> section. Default is a constant in this module.

-status => $html_string
Optional. Defines a message for the status field. This message will be displayed, if there is no error_msg or success_msg. I.e. in place of an empty status field.

-head => $html_string
Optional. This is a title that will be displayed as the first thing of the content part of the HTML page.

-css_style => $abs_url
A script may define a special CSS file by giving its absolut URL (may be without host, but should start with a /) from document root; I.e. Vip->base_url_htdocs . "mystyle.css".

-logout => 1
Only set by the script that processes a logout. It signals to the page_header method that the validation action field should contain a 'Restart' link.

print $style->page_footer( )
The page_footer method closes the content part, including page footer and HTML end code. Again, all this is returned as a string, which should be printed to STDOUT. This method should be replaced by a method of your application.

$logo = $style->logo( );
This method is called internally from page_header. It returns the logo which is displayed on top of each HTML page. This method should be replaced by a method which generates the logo of your application.

Error und Success Messages

A normal CGI script first checks the input of the current request; it may contain input of a previouse written HTML from. If there is input, and it passes plausibility checks, an action is performed and the request is typically redirected to an other script, which will continue the dialog with the user.

If there is no input, or if the in input checks generate error messages, the script prints its own page which typically includes a HTML form (and/or links to other application features).

The following methods support error handling and success messages in such an environment.

$style->error_msg( $html_string )
Stores a message which will be included in the next page_header status field. The message can be any HTML formatted string, that will fit the status field. It is expected to be HTML escaped.

Only one error should be reported, then focus may be set to the offending input field (see focus below) and then the scripts page generating subroutine should be called.

$style->focus( $form_element_name )
$style->focus( $form_element_name, $form_name )
Most errors concern the input of a textfield. Your script may put the focus on a form element. If there is more than one form in a page, you should give each form a name attribute and specify the form name in the focus call as well. If your page contains just one form, there is no need to use a form name.

Your subroutine, which writes the HTML page with a form, may itself put the focus on an input element - usually the first text field. If there is more than one focus method call, the value passed with the first call sticks. I.e. the focus given with the error message will override a later specified default focus of your form writing subroutine.

$style->success_msg( $string )
If a scripts fullfills a request, it should echo a success message to the surfer. The method success_msg stores such a message. It can be any HTML formatted string which will fit the status field. There may be several success messages. They will be shown together, separated by a semicolon. The first letter of the first success message will be translated to upper case; there will be a dot added at the end of the last success message.

While error_msg and focus have only an effect if they are followed by a page_header call in the same script, success_msg are stored in the CGIsession session storage and can be displayed even after a redirect. This allows simple scripts, which display a form, process its input and - on errors - redisplay the form with an error message and the focus on the offending input field. When the input is accepted, the script performs the necessary actions, reports them and redirects to the next script, which will continue the dialog in the same manner.


The navigation is based on a tree of links to features of your application. The tree may have any number of branches. At any one time, only one branch can be expanded (visible). Features of your application may be inaccessible for a session (depending of properties, which define which features of an application are accessible for a session). Inaccessible features may be greyed or invisible (depending on configuration, see below).

Navigation Tree Definition

The default navigation tree is defined in array @nav_elements in this module. Whenever you add a new feature to your application, you should add new entry in this default @nav_elements data structure, if the new feature should be accessible through the navigation tree.

Each session may have private copies of this navigation tree. Private copies can be modified - they could contain personal links like links to items in a cart of a virtual shop.

Each element of @nav_elements represents a navigation tree entry (= link to a feature of your application). The entries are displayed in the order of the array.

Each entry is a hash with the following key/value pairs:

name => unique_name
Required. A unique identifier. As a convention the name consists of words separated by underlines representing the path in the tree:

level => number
Required. A number which defines how deep the entry should be indented.

Top level entries have a level of 0. They are always shown in the navigation tree.

An entry with level > 1 is only shown, if its branch is expanded.

branch => name
Required for elements with level > 0. This element is used to determinate, if a element should be displayed or be hidden because it is in a not expanded branch of the tree. Often, a group of features should be expanded or shrinked together; this can be accomplished by giving them the same branch name. See method navigation below.

property => property_name
Optional. Some features of an application may be accessible only to sessions with a special property. This element defines which property is required for a session to use this feature. If a session has this property, the navigation entry will be displayed as a link; otherwise it may be greyed or invisible, depending on inaccessible attribute (see below).

inaccessible => 'hidden'
inaccessible => 'greyed'
Optional. Defines how inaccessible navigation elements should be treated. This value can be set from different sources. They are in descending priority order:
  1. Controlled by the script that generates the page:
  2. Argument -inaccessible=>$string of method navigation (see below)

  3. Definition of the navigation tree:
  4. Value to key inaccessible in the navigation element hash in array @nav_elements.

  5. Preferences of a session:
  6. $cgi->session_data('inaccessible_navigation_elements' => 'greyed') $cgi->session_data('inaccessible_navigation_elements' => 'hidden') If undef (the default) see below:

  7. 'greyed' is the last fallback.
link => array reference
Required. This is a reference to an array with arguments to method link_to_script of CGIsession.

Configuring the Navigation.

$style->navigation( ... )
Sets up the navigation. It should be called befor page_header or any method which will modify (a private) navigation tree definition array.


Entries in the @nav_element with level=>0 are always considered expanded. Entries level=> greater than 0 belong to a branch of the tree of which only one branch can be expanded.

An entry in the @nav_element defines its branch position with a branch =>branch_name attribute.

By calling method $style->navigation a script defines which branch should be expanded how deep with a -expand=>... argument.

 | Tree Position:    |   Scripts expand the branch in which they are:         |
 |                   |                                                        |
 | @nav_element      |           $style->navigation(-expand=>                 |
 |   branch=>        |  plants  |  animal  |  animal_dog  | animal_dog_snoopy |
 | animal            |    no    |   yes    |   yes        |   yes             |
 | animal_dog        |    no    |    no    |   yes        |   yes             |
 | animal_dog_snoopy |    no    |    no    |    no        |   yes             |
 | animal_dog_wauwau |    no    |    no    |    no        |    no             |
 | animal_cat        |    no    |    no    |    no        |    no             |

The currently executing task should be highlighted in the navigation. Its unique name attribute should be passed here. For best results, it should be in the expanded branch.

Selects a session private @nav_element array which may be modified by methods listed below ( insert_nav_elements, replace_nav_elements and save_nav_elements methods). $nav_name may be any name that conforms to Perls naming conventions; it is used as a filename in the $cgi->session_directory which is generated by CGIsession. An application may define several private @nav_element arrays, they are distinguished by their $nav_names.

If the private @nav_element array does not yet exist, it is created and initialised with the values of the default @nav_element array.

'Private' in this context means 'private to a session', not private to a script. All scripts of an application may access any private navigation tree definition of the same session by specifying its nav_name in the $style->navigation( -customised=>$nav_name call. If a script does not specify a private navigation tree in its $style->navigation(...) call, it will use the default @nav_element array - it this sense, a private navigation tree may also be private to a script, or a group of scripts.

If -customised=>... is omitted, the default @nav_element array will be used which can not be modified. This may be what you want for most simple applications.

Changing the Navigation Tree

It may be desirable to add session private elements to the navigation tree, like the surfers mail folders as a subelement of a navigation element 'Mail'. In such a case, a script should first make a private copy of the default @nav_element array and then modify this copy and finally save the modified @nav_element array.

To make a private copy, just call method $style->navigation( ... ) with an additional argument -customised=>$nav_name. If the private @nav_element array called $nav_name is not found, it will be generated and initalised with the values of the default @nav_element array; if it is found, it is loaded.

If a script wants to inspect the navigation tree, it may get a reference to the @nav_element array with a call to $style->get_nav_elements. With methods insert_nav_elements and replace_nav_elements the private @nav_element array may be modified, while method save_nav_elements is used to write the private @nav_element array back to the disk file where it was read from.

$ary_ref = $style->get_nav_elements;
Returns a refernce to the currently selected @nav_element array. Should be called after method navigation.

$style->insert_nav_elements( $after_name, @elements )
Inserts navigation elements in a private navigation tree. $after_name specified after which element the new elements should be inserted; the unique_name of an entry should be specified. If that $after_name is not found or is a false value, the method places the new elements in front of all other elements. Don't forget to call $style->save_nav_elements if your modification should be permanent.

$style->replace_nav_elements( $old_name, @elements )
Replaces an element in the navigation tree. If no new elements are supplied, the element named $old_name is deleted. If $old_name is not found, new elements will be inserted in front of all other elements and no element will be deleted. Don't forget to call $style->save_nav_elements if your modification should be permanent.

Writes the (private) @nav_elements structure to the file from which it was loaded (loaded by calling method $style->navigation( -customised=>$nav_name )

Greyed Text

$html_string = $style->greyed( $string );
Returns the argument $string enclosed with tags (plain HTML or HTML/CSS) which directs browsers to display the string in grey. It is mostly used to display links to inactive or inaccessible features.


Table objects represent a HTML table. They are simple to use and keep the scripts clean of HTML or CSS code. The VipStyle object can produce table objects.

     my $table = $style->table( -class=>'input' ); # <- $style is the VipStyle object
     print $table->row( -class=>'head' );
     print $table->hcell(-colspan=>3, "You can send a mail here:");
     print $table->row;
     print $table->cell("Mail To:");
     print $table->cell($cgi->textfield(-name=>'mail_to'));
     print $table->cell( -class=>'comment', "Enter a RFC-822 email address");
     print $table->row;
     print $table->cell("Mail message:");
     print $table->cell(-colspan=>2,  $cgi->textarea(-name=>'body', ...) );
     print $table->etable;

Table Object Constructor

The VipsStyle object can create table objects:

$table_object = $style->table;
$table_object = $style->table( -class=>table_class );
$table_object = $style->table( -sorted_cell=>index );
$table_object = $style->table( -class=>table_class, -sorted_cell=>index );
Creates a table object.

The table_class defines the purpose of a table, and the sorted_cell argument may specifies a column which should be highlighted.

-class => 'list'
is for lists. This one is very compact and has alternating background of light blue shades for each row.

-class => 'bluelist'
the same in darker blue.

-class => 'yellowlist'
same in yellow.

-class => 'greenlist'
same in green.

-class => 'redlist'
same in red.

-class => 'info'
is for infomations and list; this table will be yellow.

-class => 'input'
is for tables with form input, where the surfer should enter data; it will be green.

-class => 'confirm'
is for tables with information that should be confirmed (like 'do you really want to ...'); it will be red.

If no class is specified, the background color will be blue. In that case, each row may specify a color (see below).

If an illegal class is specified, the table method will die. =item -sorted_cell=>index

One of the columns may be highlighted (usually because the data in that column is sorted). If your application needs a highlighted column, just specify its number (columns are numbered from left to right, starting with 0) in the object constructor.

Table Rows

There is only a method to mark the beginning of a new row.

print $table_object->row;
print $table_object->row( -class=>row_class );
This starts a new row including some buffered data. The result of this method should be printed.

row_class may be used when no table class was specified and the rows should be colored depending on the urgency of its data. The following row_class values are defined:

-class => 'alert'
Should be handled by the surfer: Red

-class => 'watch'
Needs watching by the surfer: Yellow

-class => 'ready'
Is OK, no action required by the surfer: Green

-class => 'finished'
Historical data: Grey

-class => 'head'
For table headers. This will be darker than table data and will not change its background when sorted. Mostly used for a title on top with just one call spanning all columns.

More arguments can be passed as key value pairs. They will be included in the <tr> tag. I.e. $table_object->row( -alt=>'test' ); will generate <tr alt='test'>. Most row attributes are set in the CSS (or plain HTML code), particularly valign and bgcolor.

Table Cells

There are two kinds of cells: hcell for headers (like HTML <th>...</th>) and cell for normal data (like HTML <td>...</td>). The result of this methods should be printed.

print $table_object->cell( ... );
print $table_object->hcell( ... );
Both methods return HTML code for a cell.


-class => 'comment'
For cells which contain comments or explanations. The font will be smaller. A comment cell can not be sorted (should not be named in the table constructor as sorted_cell).

-colspan => number
Even with a colspan, the highlighting of columns should work.

-rowspan => number
but rowspans may confuse the highlighting of columns.

-align => 'right'
Any attribute (like -align) is included in the HTML tag (without the beginning '-'. I.e. -align => 'right' generates <td align='right'. =item strings

After this optional arguments, there may follow any number of HTML encoded strings, which will be the contents of the cell.

Terminating a Table

print $table_object->etable;
Method etable returns the termination of a table, including some buffered data. The result of this method should be printed.


The methods in this class can produce plain HTML code or HTML code for CSS. There is a style.css file in the VIP base package which will produce the same output as the plain HTML code.

The methods produce plain HTML if the objects no_css flag is set. This flag is initalised in method new by checking $cgi->session_data('no_css'). Method new accepts also an argument -no_css => $boolean which, if specified, sets both, the no_css flag in the object state and the default for the session in $cgi->session_data('no_css').

Table objects will inherit the no_css flag from the VipStyle object which was used to generate the table object. There is also a -no_css => $boolean argument in method table which will override this default.

The CSS style definition file can be set from different sources:

  1. the executing script:
  2. print $style->page_header( -css_style => Vip->base_url_htdocs . 'filename.css' )

  3. session preferences:
  4. $cgi->session_data( css_style => Vip->base_url_htdocs . 'filename.css' ) no minus here ;-(

  5. last fallback default
  6. Vip->base_url_htdocs . 'style.css' is defined as a constant in this module.


cell( ) creates a table cell (HTML <td>)

 print $to->cell('html encoded text');  # just one argument
 print $to->cell( -class => 'comment',
                  'html encoded text'); # smaller font

There can be several strings to form the cells content; they should be placed at the end of the argument list. The follwing arguments can be placed in front of any text:

                  -colspan => 3,
                  -rowspan => 2,
                  -align => 'right',
                  -align => 'center',

error_msg( ) reports/checks for an error message

 $style->error_msg("String in HTML code."); # report an error
 $string->error_msg;                        # checks if an error was reported

An error message should be HTML encoded, it should begin with an uppercase and be terminated with a dot.

etable( ) terminates a table

 print $to->etable;     # no arguments

focus( ) sets the focus on a input field of a HTML form

 $style->focus('field_name');               # if only one HTML form on a page
 $style->focus('field_name', 'form_name');  # if several forms, name them

If the focus is set several times, the first call is used, subsequent focus calls are ignored.

get_nav_elements( ) returns a handle to the current navigation tree. See also chapter Navigation Tree Definition

 $aref = get_nav_elements;  # no arguments; should be called after C<navigation>

greyed( ) encloses a HTML string with tags for grey text

 $html_string = $style->greyed($html_string);

hcell( ) creates a table cell (HTML <th>)

 print $to->hcell('html encoded text');  # just one argument
 print $to->hcell( -class => 'comment',
                   'html encoded text'); # smaller font

The follwing arguments can be placed in front of any text:

                   -colspan => 3,
                   -rowspan => 2,
                   -align => 'right',
                   -align => 'left',

insert_nav_elements( ) inserts new elements into the navigation tree structure. The navigation tree must be a private copy (see navigatioon); Method insert_nav_elements should be called after method navigation. Navigation tree structure see chapter Navigation Tree Definition To save the changed navigation tree structute use save_nav_elements.

 $style->insert_nav_elements($after_name, @new_elements); # after_name is a unique_name
 $style->insert_nav_elements('', @new_elements);          # insert in front

logo( ) returns the logo of your application

 $html_string = $style->logo;  # no arguments

You should replace this method. It is called internally by page_header to get the logo on top of each page.

navigation( ) sets navigation options for a page. Should be called before page_header or any method to edit a private navigation tree.

                     -highlight => $unique_name,        # required
                     -expand => $branch_name,           # tree branch to expand
                     -inaccessible => 'greyed',         # inaccessible elements are grey
                     -inaccessible => 'hidden',         # inaccessible elements hidden
                     -customised => $private_tree_name, # creates/loads a private tree

new( ) initalises the VipStyle object

 $style = VipStyle->new( -cgi => $cgi ); # needs the handle to CGIsession object
 $style = VipStyle->new( -cgi => $cgi,
                         -no_css => 1);  # forces plain HTML for a session until reset:
 $style = VipStyle->new( -cgi => $cgi,
                         -no_css => 0);  # forces CSS for a session until reset (see above).

page_footer( ) returns a HTML page end

 print page_footer;                      # no arguments

page_header( ) returns a HTML page begin

 print $style->page_header( );           # may be called without arguments
                           -head   => 'HTML string',       # Contents heading
                           -title => 'IOS-8859-1 string',  # HTML <head><title>
                           -status => 'HTML string',       # for an empty status field
                           -logout =>1,                    # only for logout.cgi
                           -css_style => 'absolte URL',    # URL of style.css

replace_nav_elements ( ) replace an element in the navigation tree structure by zero to any number of elements. The navigation tree must be a private copy (see navigatioon); Method replace_nav_elements should be called after method navigation. Navigation tree structure see chapter Navigation Tree Definition To save the changed navigation tree structute use save_nav_elements.

 $style->replace_nav_elements($unique_name);                 # delete
 $style->replace_nav_elements($unique_name, @new_elements);  # replace

row( ) starts a new row of a table (and terminates a previouse row)

 print $to->row;                      # usually no arguments
 print $to->row( -class => 'head' );  # for headings spaning all columns of a table

For tables without a class, the rows may have a class:

 print $to->row( -class => 'alert' );    # row is red
 print $to->row( -class => 'watch' );    # row is yellow
 print $to->row( -class => 'ready' );    # row is green
 print $to->row( -class => 'finished' ); # row is grey

save_nav_elements saves a private navigation tree structure to a file

 $syle->save_nav_elements; # no arguments

success_msg( ) reports/checks for a success message

 $style->success_msg("string in HTML code"); # report a success
 $string->error_msg;                         # checks if an error was reported

A success message should be HTML encoded, be very short, begin with a lowercase and end without a dot

table( ) Creates a table object

 $to = $cgi->table();                         # default
 $to = $cgi->table( -class => 'list' );       # zebra paper
 $to = $cgi->table( -class => 'bluelist' );   # zebra paper blue
 $to = $cgi->table( -class => 'yellowlist' ); # zebra paper yellow
 $to = $cgi->table( -class => 'greenlist' );  # zebra paper green
 $to = $cgi->table( -class => 'redlist' );    # zebra paper red
 $to = $cgi->table( -class => 'info' );       # table of informations
 $to = $cgi->table( -class => 'input' );      # input fields
 $to = $cgi->table( -class => 'confirm' );    # info that should be confirmed
                    -sorted_cell => number,   # a column mmy be highlighted
                    -no_css => 1              # force plain HTML output


Vip.pm defines installation depending constants. CGIsession.pm is the class to access session data; it is an extension of CGI.pm (from CPAN). SaveLoad.pm is a class to dump and reload complex data structures. Properties.pm handels properties of a VIP application; properties define which features of an application are available for a session. style.css is the default CSS; it is distributed with the VIP base package and is in the htdocs tree.


Copyright 2004-2013 Thedi gerber@id.ethz.ch