This document describes the project inosid for developers.
sigui provides a toolkit for developing graphical interfaces for browser based applications.
This is a template and plugin driven approach which can be extended and modified easily.
There is a skeleton offering flow control, handling of configuration, storing of user specific data and so on.
Each page of the application is handled by a plugin implemented by a class derived from Page to administrate this page.
The basic html page is defined in a template. The content area of
the page will be created from the plugin.
This allows using one template for all pages (equal design).
The standard http process only allows access to the input field values if a button inside the form has been pushed. Therefore the navigation uses buttons instead of links.
Without this construction the user must push a "store" button and the data will be lost if he does not (very uncomfortable).
With the navigation by buttons the plugin can store the field values and then it changes the page.
The plugin class must overwrite the abstract methods of the class Page. See page.php.
The following methods are predefined but can be overwritten.
There are helper functions in the base class Page...
.. and in the class Session:
The template contains markers which will be replaced by the core modules or the plugin.
The content area will be filled by a plugin. It should use a template to divide design and code. The plugin should use markers to communicate with the template.
The filling of the input fields with values inserted earlier will be done by the core modules. Therefore the names of the fields must be known.
Note: X stands for an uppercase field name.
The file inosid.conf contains configuration data which are used for all clients.
# List of the page names separated by ','. # The series defines the effect of the Back and Next buttons. # The page name is the name of the plugin. .gui.pages=home,boot,user,network,run
The configuration has a part for global definitions: these definitions starts with '.'. The other parts are plugin dependent. The definitions in these parts start with the plugin name.
When the user changes the pages (using the back or the next button) the field values will be stored in a file. The filename is client specific: the remote ip address is part of the name. This is not perfect but good enough.
user.user=jonny user.pass=123 user.pass2=123
If the http header ($_GET or $_POST) contains a button the input field will be set from the http header. Otherwise the fields will be set from the user data. Therefore the field values in the content template must contain markers: ###VAL_X### (X is the uppercase fieldname).
The field validation should be done inside the plugin method onButtonClick().
If a field value is valid the value must be stored in user data:
$this->session->userData->setValue(pluginName,
fieldName, fieldValue)
Otherwise an error message should be set: $this-<setFieldError(fieldName,
errorMessage)
siguibui projects can maintance menus.
At this moment only projects with static pages handle automatically menus.
The content and the structure of a menu depends on the language
and will be defined in the file config/menu_<language>.conf.
# Format: <indent-level> <id> <link> <text> * sm1 welcome siduction OS Manual ** sm1a welcome#welcome-gen siduction OS Manual ⇒ *** - credits#cred-team Credits ** sm1b welcome#how-to How to use this manual ⇒ *** - welcome#how-to How to use this manual *** - welcome#table-contents Table of Contents ** sm1c help#help-gen Getting Help ⇒ *** - help#help-gen Where and how to get help *** - help#paste IRC !paste ** - wel-quickstart#welcome-quick siduction Quick Start Guide * sm2 cd-dl-burning ISO Content, Releases, Download Mirrors and Burning ** sm2a cd-content#cd-content ISO Content and system requirements ⇒ *** - sys-admin-release#rolling Release Notes ** sm2b cd-dl-burning#download-siduction siduction Mirrors, Downloading and Burning ⇒ *** - cd-dl-burning#md5 md5 Checksum *** - cd-dl-burning#burn-nero Burning in Windows *** - cd-dl-burning#burn-linux Burning in Linux *** - cd-no-gui-burn#burning-no-gui burniso script *** - cd-no-gui-burn#burn-no-gui-gen Burning without a GUI *** - cd-dl-burning#download-siduction siduction Download Mirrors
The design of the menu can be defined in config/menu.parts.txt
.
It contains a definition for each hierarchical level.
Only in very special cases the following example must be changed.
LEVEL_0: <ul> ###ENTRIES### </ul> ENTRY_0: <li###class_current###> <a href="###link###">###title###</a> ###SUBMENUS### </li> LEVEL_1: <ul ###id###> ###ENTRIES### </ul> ENTRY_1: <li###class_current###> <a href="###link###">###title###</a> ###SUBMENUS### </li> LEVEL_2: <ul class="sub2-menu"###id###> ###ENTRIES### </ul> ENTRY_2: <li###class_current###><a href="###link###">###title###</a></li> CLASS_CURRENT: class="current-item" ID: id="###id###" END:
LEVEL_<level>
defines the body of a menu list with the same level.ENTRY_<level>
defines the body of a menu item at this level.###ENTRIES###
will be replaced by all bodies of the menu list.###SUBMENUS###
will be replaced by the submenus of the menu item (if there are any).###CLASS_CURRENT###
will be replaced by the template CLASS_CURRENT
if the menu item belongs to the tree of the current displayed menu item.###link###
, ###text###
are the properties
of the menu item.###id###
will be replaced by the template ID
if the menu item has an id not equal to '-'.If there are more than one menu the part names must be completed by a prefix, e.g. TOP_MENU_LEVEL_0, TOP_MENU_ENTRY_0 and so on.
A good example for a project with static pages is the siduction manual. There are more than 50 pages. Realized with true static pages the work for maintance is too large: If there is a change in the html-structure of the menu, each of the pages must be changed too.
The solution is a project derived from siguibui. The common design of all pages will be defined only once.
Every static page should exist in each language. This forms the directory tree.
static en welcome-en.htm content-en.htm de welcome-de.htm content-de.htm pt-br welcome-pt-br.htm content-pt-br.htm
Because of data migration and easy development the content file of the static page
can be a valid HTML or XML file. The system extracts the pure content (without header,
menu...) and puts this content into the template config/<project>.html
.
The extraction is driven by pattern matching:
There are 2 parameters in config/<project>_<language>.conf
to control this extraction:
static.content.start=id="main-page" static.content.end.ignoreddivs=1
static.content.start
: This defines a text pattern where
the interesting content starts. A good choice is the class or id of the spanning div.static.content.end.ignoreddivs
is a count. So much <div> in
top of <body> will be ignored.All texts are stored in the configuration files, none in the program code and none in the templates.
For each supported language there must be a configuration file. The file name convention: <name>_<language>.<ext>, e.g. inosid_de.conf
Templates can contain markers ###txt_X### (X is being a name with letters, digits and '_'). Entries in the configuration must contain <plugin>.txt_X or default.txt_x. <plugin> is the name of a plugin. If the plugin using the template has a so defined entry this value will be substituted. If not, the plugin independent variant will be used.
Rules are needed to integrate the plugins. For a simple explanation, an example: user (a page asking for username and password)
This chapter offers solutions for tasks belonging to development with the toolkit.
The example project is named net-center.
Task:
A input field for a ipaddress should be added to the page wlan.
###txt_ipaddress###: <input type="text" name="ipaddress" value="###VAL_IPADDRESS###">
wlan.txt_ipaddress%=IP Address
wlan.txt_ipaddress%=IP-Adresse
function getInputFields()
:$rc = array('mode', 'ipaddress', 'device');
$this->setEmptyToDefault('ipaddress', 'wlan.DEFAULT_IP');
$curValue = $this->session->userData->getValue('wlan', 'ipaddress');
Note:
If the field value should be empty on a redisplay the makro ###VAL_...### must not be set.
Task:
A combobox for a mode should be added to the page wlan.
There are two alternatives (dhcp and static address) which do not change. But the values depend on the current language.
Therefore they must be stored in the configuration file.
<select name="mode" size="2">
###OPT_MODE###
</select>
wlan.opt_mode%=DHCP;Static IP
wlan.opt_mode%=DHCP;Statische IP
function getInputFields()
:$rc = array('mode', 'ipaddress', 'device');
$curValue = $this->session->userData->getValue('wlan', 'mode');
Task:
A combobox for a device should be added to the page wlan.
The values (e.g. wlan0 and wlan1) are dynamic: they must be calculated by the program.
<select name="device" size="1">
###OPT_DEVICE###
</select>
function getInputFields()
:$rc = array('mode', 'ipaddress', 'device');
function _construct()
:$this->setDefaultOption('device', 0, true);
build()
:$this->session->userData->setValue('wlan'
, 'opt_device
', '-');
function build()
:$this->fillOptions('device', true);
$this->content
$curValue = $this->session->userData->getValue('wlan', 'device');
Task:
The value of the field ipaddress on the page wlan
must be checked for a correct syntax. In the case of an error a message must be displayed.
<field name="ipaddress" value="###VAL_IPADDRESS###">
###ERROR_IPADDRESS###
function getInputFields()
:$rc = array('mode', 'ipaddress', 'mode');
function onButtonClick()
:if (strcmp($button, 'button_next') == 0){
$value = $this->getFieldValue('ipaddress');
if (! preg_match('^(\d{1,3}\.){3}\d{1,3}', $value))
$this->setFieldError($this->i18n('err_ipaddr'));
}
wlan.err_ipaddress%=No valid IP address, e.g. 192.168.7.1
wlan.err_ipaddress%=Keine gültige IP-Adresse, z.B. 192.168.7.1
Task:
A certain screen area should be displayed only under some conditions. The example is a division
to show the last command log message. This will be showed only if a command is executed.
LAST_LOG:
<h2>###txt_header_last_log</h2>
<div class="log">###txt_last_log###
</div>
$this->readContentTemplate();
$this->readHtmlTemplates();
if ($hasMessage)
$this->clearPart('LAST_LOG');
else {
$this->replacePartWithTemplate('LAST_LOG');
$lastLog = $this->session->readFile('last.log');
$this->content = str_replace('###txt_last_log###', $lastLog, $this->content);
}
if (! $hasMessage)
$this->replacePartWithTemplate('LAST_LOG', 'NO_LOG_MESSAGE');
else
$this->replacePartWithTemplate('LAST_LOG');
Note:$this->replacePartWithTemplate('LAST_LOG')
$this->replacePartWithTemplate('LAST_LOG', 'LAST_LOG')
file ::= {<template-definition> }+ template-definition ::= <header> <body> header ::= <name> ':' '\n' body ::= { <body-line> }+ body-line ::= <html-code-or-makros> '\n'Example of a template definition file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="###LANGUAGE###"> <head> <title>###txt_title###</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style type="text/css" media="all">@import url("../config/content.css");</style> ###META_DYNAMIC### </head> <body class="body-main"> <div><img class="header-img" alt="header logo siduction" src="../images/siduction-logo-web.png" /> </div> <div id="content"> ###CONTENT### </div> <!--content --> </body> </html>