
WebBox-es
==========

What is a WebBox
----------------
A WebBox is a template which has also its own PHP code, which
handles its server-side logic. It is an almost self-contained
and independent template which can be easily included in other
pages or in other projects. Each page of a webApp should contain
at least a webox, unless it is very simple (doesn't have 
server-side logic). A webox can be composed of other weboxes.


How it is denoted
-----------------
It is denoted by the tag <WebBox> and it has an ID attribute:
    <WebBox ID="boxID">
        <!-- content of WebBox -->
    </WebBox>   
The identifier of the box is very important and must be
different for each box used in the application. 


The PHP code of a webox
-----------------------
When the framework loads a WebBox it looks for a file named 
"boxID.php" in the same folder where the WebBox template is
("boxID" is the identifier of the webox). If it finds such a 
file, it includes it. This PHP file contains mainly 3 functions
which are named "boxID_eventHandler($event)", "boxID_onParse()",
and "boxID_onRender()". These functions are optional, if they
are declared then the framework uses them, if not then nothing
happens. The "boxID.php" file may also contain other functions,
but only if they are needed by the above functions; the framework
does not use them.

So, at the time that the framework is about to load (parse) the
WebBox, it includes the "boxID.php" file, and then calls the 
functions "boxID_eventHandler($event)" and "boxID_onParse()". Later,
when it is about to render (generate the HTML code of) the WebBox,
it also calls the function "boxID_onRender()".


The function boxID_eventHandler($event)
----------------------------------------
The function "boxID_eventHandler($event)" is used to handle the
events of the WebBox. It is called by the framework only when an
event is sent to this WebBox (from outside or from inside it). An
event sent to the WebBox has the syntax "boxID.event_name(args)". 
The parameter "$event" of the event handler is an object 
of class Event, which has the variables $name, $args, $targetBox etc.
This object is constructed by the framework and is passed 
to the event handler when it is called.
The event handler typically has a switch statement on the 
variable '$event->name', and performs some actions depending on 
the case. It also can extract and use the arguments of the event
from the '$event->args'.

(For more details see: 'events.txt' .)


The function boxID_onParse()
----------------------------
The function "boxID_onParse()" is always called (if it exists)
before the box is parsed. It is usually used to give value to
some template variables that affect the parsing. E.g. if we have
this line in a template:
    <Include SRC="{{#content_file}}" />
then the variable {{#content_file}} must have a value before this
line is parsed, and usually this value is given in the onParse()
function, according to a certain logic.

It can also be used to give an initial value to a session variable
that keeps the state of the webox. Usually a WebBox is like an 
object that can be in different states. To keep the state of the
webox a session variable named "boxID_state" may be used. When
the webox is displayed for the first time, nothing guaranties that
this variable exists in the session and is initialised. This
initialisation (if it doesn't exist) can be done in the onParse() 
function.


The function boxID_onRender()
------------------------------
The function "boxID_onRender()" is always called (if it exists)
at the time that the template is being rendered. It is usually 
used to give value to the {{#variables}} that are used inside the
template. This value is given using the functions WebApp::addVar()
and WebApp::addVars().
(see the documentation about the template variables for more details)


The files related to a webox
-----------------------------
The files related to the webox "boxID" are: boxID.html, boxID.js, 
boxID.css, boxID.rs, boxID.php, boxID.db . All of them are optional, 
except the first one. Files boxID.js, boxID.css, boxID.rs are 
the same as for the templates and must be included manually 
in the webox. Files boxID.php and boxID.db are specific for the 
weboxes and are included automatically by the framework, 
if they exist in the same folder with the webox. 
Also related files may be images, subtemplates, etc.

The 'boxID.js' file contains the javascript functions related to the 
webox (same as for the templates). It is included like this: 
    <script language="javascript" src="{{#./}}boxID.js"></script>
    
The 'boxID.css' file contains the stylesheet of the webox. It is
included like this:
    <link rel="stylesheet" type="text/css" href="{{#./}}boxID.css">

The 'boxID.rs' file contains the recordsets of the webox that are
used in the layout (for the <Repeat> tags). It is included like
this:
    <Include SRC="{{#./}}boxID.rs"/>
    
The 'boxID.php' file contains the PHP code of the webox. It is included
automatically by the framework, if it exists.

The 'boxID.db' file contains the <dbCommand> and <Recordset> elements
that are used in the php code. It is included automatically by the 
framework, if it exists. (See the documentation about interacting
with the database for more details).


Some recommendations about using weboxes
----------------------------------------
These rules and guidelines are not required by the framework, but
they are recommended for more readability and more flexibility.

It is better that WebBox-es be declared in separate template files,
and the template file containing the WebBox be named "boxID.html".

It is better that a WebBox and all the files related to it be 
placed in a folder with the same name as the boxID. 


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


-------- the PHP code of a webox -----------------------
* - The PHP code of a webox: <WebBox ID="boxID" 
    is placed in the file "boxID.php" which is in the
    same folder as the template containing the webox.
    
    The code of the webox now is organized inside a class:
    "class boxID extends IWebBox {...}"
    which extends the interface (or the abstract class) IWebBox.
    This makes the PHP code of the application more object-oriented
    and better organized.
    
    The class "boxID" can override the functions:
    eventHandler($event), onParse() and onRender()
    of IWebBox, or can define other functions that can be
    used inside these functions. These functions replace 
    the old functions: boxID_eventHandler($event), boxID_onParse()
    and boxID_onRender()


---------- the function init() ----------------------------------
* - The class of the webox can also define the function init(),
    which is like the functions eventHandler(), onParse() and
    onRender(), and overrides the abstract function with the same
    name of the class IWebBox. This function is called only when
    the webox is loaded for the first time (only once in a session
    of the application). 

    This function is the right place for initializing the state 
    vars of the webox with default values. Previously, this was 
    done in the onParse() with a statement like this:
     if (!isset($session->Vars["state_var"]))
     {
        $session->Vars["state_var"] = "initial_value";
     }
    Now it should be done in the init() function, like this:
     $this->addSVar("state_var", "initial_value");


----- state vars (or session or persistent vars) added to webox ----
* - Now each webox can have its own state vars (or session vars, or
    persistent vars). Inside the class of the webox, its state vars
    can be accessed like this:
    $this->addSVar ($var_name, $var_value);
    $this->addSVars($associated_array);
    $this->setSVar ($var_name, $var_value);
    $this->setSVars($associated_array);
    $var_value = $this->getSVar($var_name);
    $assoc_arr = $this->getSVars();
    These variables can be accessed inside the webox in the usual way:
      {{var_name}} 
    and they are valid only in the scope of this webox (and shadow any
    other {{variables}} with the same name that are defined in the
    enclosing scopes.

    In case that some state variable of a webox needs to be used
    from the template of another webox, they can be accessed like this:
     {{boxID->var_name}}

    From the JS code as well, they can be accessed like this:
     session.setVar("boxID->var_name", var_value);   etc.

    Also, when you need to access the state var of another box from
    the PHP code of this webox, you can use this function:
    $var_value = WebApp::getSVar("otherBoxID->var_name");
    The function $var_value=WebApp::getSVar($var_name) can also 
    be used to get the session variables (instead of 
    $var_value=$session->Vars[$var_name]).
    Also the function:  WebApp::setSVar($var_name, $var_value)
    is available (instead of $session->Vars[$var_name] = $var_value;),
    and the function:  $wb = WebApp::getWBox("wbox_id");
    which returns a reference to the webox with the given id (this
    reference can be used to access the variables, state variable or
    functions of this webox, e.g. $wb->getQuery(); ).
    
    If the constant DEBUG_STATEVARS in the 'config/const.Settings.php'
    is set to true, then the framework outputs the state variables
    for each webox.

* - The callback function onLoad() is renamed to onParse(). As before,
    it is called just before the webbox is parsed. 

-----------------------------------------------------------------
* - The framework supports WebClasses and WebObjects.

    <WebClass ID="className" Path="path/to/className.php">
            <Parameter name="param1" default="default value" />
            <Parameter name="param2" />
        <!--# . . . . . . . . . . . . . . . . #-->
        <!--# the template of the web class   #-->
        <!--# . . . . . . . . . . . . . . . . #-->
    </WebClass>

    <WebObject Class="className" name="wObj1" param1="value1" param2="value2" />
    <WebObject Class="className" name="wObj2" param2="value2" />
    <WebObject Class="className" name="wObj3" param1="{{nr}}+1" param2="red" />

    The element <WebClass> defines a web class, but it by itself
    does not produce any HTML output in the rendered page. The element
    <WebObject> declares an object of the class and the content (the template)
    of the <WebClass> is used to render this object.

    The 'Path' attribute of the <WebClass> declares the path of the 
    file that defines the PHP code of the WebClass. It is optional, 
    and if it is not given, then the current folder (the folder of the
    template that contains the <WebClass> definition) is searched for
    the file "className.php".

    The <Parameter> elements declare the names and optionally the default
    values of the parameters of the webobjects. (The current implementation
    requires that they come immediately after the <WebClass> line and have
    no empty lines or other lines between them, otherwise they will not be
    parsed correctly.) These parameters can be used inside the template of
    the webclass like template variables, e.g. {{param1}}. If a parameter
    doesn't get a value in the <WebObject> declaration, then its default
    value is used (if it doesn;t have a default value, then it is handled
    like an undefined variable). When a <WebObject> is rendered, the value 
    of the parameters is evaluated as a mixed expression (a PHP expression
    that contains {{template vars}}).

    When several objects of the same class are declared, the template of the
    webclass is repeated for each of them. The webclass designer should
    take this into account when building the webclass. E.g. if there is
    such an input in the webclass template:
        <input type="text" name="staff">
    There will be several such inputs in the HTML code, and its value
    cannot be accessed like this: document.form.staff.value

    ToDo: The framework declares some variables like: {{className}}
    {{objName}}, {{objID}} (which usually is {{className}}::{{objName}}),
    {{objCount}} (counts the objects of the same class, starting from 1),
    etc. These vars can be used inside the template of the webclass,
    if the webclass designer needs them, e.g.:
        <input type="text" name="staff_{{objCount}}">

    The PHP code 
    -------------
    The file "className.php", if it egzists, contains this class definition:
    <?
    class className extends WebObject
    {
      . . . . .
    }   
    ?>
    Where 'WebObject' is a class defined by the framework that supplies
    some useful functionality for all webclasses. 
    This functionality is:
        1 - The callback functions that are called by the framework at 
        certain moments during the time that the webobject is processesed.
        These callback functions are:
        + init()
        + on_eventName($event_args)
        + eventHandler($event)
        + onParse()
        + onRender()

    2 - The ability to keep persistent variables that define the
        state of the object. These state variables can be used 
        inside the "className" like this:
        + $this->addSVar($var_name, $var_value);   
        + $this->addSVar($var_name, $var_value, "DB");  
        + $this->setSVar($var_name, $var_value);
        + $this->setSVars($var_name, $var_value);
        + $var_value = $this->getSVar($var_name); 
        + $arr_values = $this->getSVars($var_name);
        + etc.
        Outside the scope of the WebClass, these state variables can 
        be accessed like this: 
            + WebApp::setSVar("className::objName->var_name", "var_value")
        + $var_value = WebApp::getSVar("className::objName->var_name");
        + {{className::objName->var_name}} (in templates)
        + session.setVar("className::objName->var_name", "var_value")
        + etc.


    WebBox-es
    ---------
    The <WebBox>-es are handled by the framework as a special case of 
    <WebClass>-es and <WebObject>-s. When the framework parses:
        <WebBox ID="boxID">
      . . . . .
    </WebBox>
    it interprets it as:
        <WebClass ID="boxID">
      . . . . .
    </WebClass>
    <WebObject Class="boxID" />
    and the ID of the created object, instead of being "className::objName"
    is just "boxID", so it is handled the same as before 
    (e.g. $var_value = WebApp::getSVar("boxID->var_name"), etc. )
    Thus, when upgrading an egzisting application, the only change that
    needs to be done is to replace:
        class boxID extends IWebBox
    with
        class boxID extends WebObject

-------- afterParse() ----------------------------
* - WebObject::afterParse()
    is like WebObject::onParse(), only that it is called after
    the WebObject is parsed.

-------- webobject vars --------------------------
* - The framework declares for each webobject these variables: 
    {{obj_id}}  -- the object id ({{class_name}}::{{obj_name}})
    {{class_name}}  -- the name of the class
    {{obj_name}}    -- the name of the object
    {{obj_count}}   -- counts the objects of the same class, 
                starting from 1
    These vars can be used inside the template of the webclass,
    if the webclass designer needs them, e.g.:
        <input type="text" name="staff_{{obj_count}}">

--------------------------------------------------------------------
* - The tag <WebObject> can be written in several lines (for making it
    more readable, in case that it has many attributes) and the parser
    can handle it. E.g.
        <WebObject Class = "listbox" Name  = "country" 
                   rs    = "rs_id" 
                   width = "---------------" />

--------------------------------------------------------------------
* - The JS code of a <WebBox> is included automatically by the 
    framework at the <head> of the page. The framework looks for
    the file 'box_id.js' (or 'class_id.js', in case of a <WebClass>)
    in the same folder with the <WebBox>. If it exists there, then
    the framework includes a line like this in the <head> of the page:
    <script language='javascript' src='path/to/box_id.js'></script>
    
    Similarly, for the CSS code, the framework includes a line like
    this: <link type='stylesheet' src='path/to/box_id.css' ....>
    in the <head> of the page.

