# SPL Module Reference: wsf

load "wsf";

    WebSPL Forms Library

    This module provides a frame work for doing application development
    with WebSPL. The basic idea is to split down the user interface into
    so-called components. Each component provides a part of the DOM tree
    which is displayed in the browser window. There is a seperate program
    task for each component - so they can act as independent as the
    programmer wants.

    This module provides WsfComponent, the base object for WSF Components,
    and WsfDocument, the object which manages the interaction with the
    Browser.

    Other Modules provide additional WSF Components. E.g.:

    	WsfDebug	WsfDialog
    	WsfDisplay	WsfEdit
    	WsfEditSql	WsfGraph
    	WsfMenu		WsfSwitch

    If the browser has support for it, WsfDocument does only send those
    parts of the DOM tree to the browser which have actually changed and replace
    them 'in place' in the current page using a little JavaScript hack.

function wsf_get_domupdate_status(@methods) ;

object WsfComponent
{
static id_counter = 0;

var id;
var sid;
var dirty = 0;
var children;
var main_task;

method add_action(url);
method add_href(url);
method add_javascript(url);
method get_html_children();
method get_html_cached();
method get_html();
method main();
method child_set(name, obj);
method child_remove(name);
method destroy();
method init();
}

object WsfDocument
{
static domupdate = wsf_get_domupdate_status();
static showiframe = 0;

var root;
var title = "";
var html_head = "";
var body_attr = "";
var callbacks;

method callback_add(type, func);
method callback_del(type, func);
method callback_call(type, %options);
method main();
}

function wsf_get_domupdate_status(@methods) ;

    Checks the HTTP Agent string and auto-detects if the browser is able
    to synamically update the DOM tree.

    It is possible to specify methods as arguments in the order of preference.
    Then this methods are checked in that order. E.g.:

    	var method = wsf_get_domupdate_status("iframe", "xmlhttprequest");

    Will return "iframe", "xmlhttprequest" or "none".

    If no arguments are given the function eighter returns "iframe" or
    "none". The "xmlhttprequest" method is left out in this case.

    Usually this is only used internally by the WsfDocument object to
    initialize WsfDocument.domupdate and doesn't need to be called by the
    user.

object WsfComponent

    The base WsfComponent object. All other Wsf Components are derived from
    this Object.

static WsfComponent.id_counter = 0;

    This counter is used by the constructor to create the id for
    new instances of Wsf Components.

var WsfComponent.id;

    The id of this component instance. It is set automatically by the
    contructor and must be included as "id" attribute in the top element
    of the HTML tree returned by get_html().

    This also is the name of the task created for this component by the
    constructor.

var WsfComponent.sid;

    The sid (session id) for the task running this component. It must
    be included as parameter 'sid' in all query strings. The methods
    add_action(), add_href() and add_javascript() should
    be used for creating links, etc.

var WsfComponent.dirty = 0;

    This variable must be set to 1 whenever it is neccessary to call
    get_html() again and refresh the browser view of this component.

    It is also possible to set this to 1 if there have been any changes
    in the children array.

var WsfComponent.children;

    An array of child components. The keys may be freely choosen. The
    get_html() method must run get_html() for all children and
    include the return value in its own output.

var WsfComponent.main_task;

    The name of the main task running the WsfDocument instance which
    is responsible for this component. This is automatically set by
    WsfDocument when checking for set dirty flags and by the
    child_set() method.

method WsfComponent.add_action(url);

    Whenever a form is generated by get_html(), this method must be
    used to create the "action" attribute in the <form> tag. A hidden
    input field for the "sid" parameter mus also be generated. E.g.:

    	<form id="$id" ${add_action(cgi.url)}>
    	<input type="hidden" name="sid" value="${sid}" />
    	...
    	</form>

method WsfComponent.add_href(url);

    Whenever a HTML link is created by get_html(), this method
    must be used to create the "href" attribute in the <a> tag. E.g.:

    	<a ${add_href("${cgi.url}?sid=${sid}&foo=bar")}>Foobar</a>

method WsfComponent.add_javascript(url);

    Whenever JavaScript is used in the code created by get_html(),
    this method must be used to create the statement which sets
    location.href to the new value. E.g.:

    	onClick="${ add_javascript("${cgi.url}?sid=${sid}&foo=bar") }"

    the URL will be quoted with single quotes in the generated code. So
    there is no problem with embedding it using "onFoobar" JavaScript
    event handlers. No additional quoting is done. So something like that
    for creating query string parameters with JavaScript is possible too:

    	onClick="${ add_javascript("${cgi.url}?sid=${sid}&foo=' + (3+5) + '") }"

method WsfComponent.get_html_children();

    A simple method for calling get_html_cached() on all children
    and concatenating the results.

method WsfComponent.get_html_cached();

    This method returns the HTML code for this component. If the
    dirty flag is set, get_html() is called to generate
    the HTML code. Otherwise a cached version of the HTML code is
    returned.

method WsfComponent.get_html();

    The method for creating the HTML code. The top HTML element must
    have the attribute "id" set to the value of the id member
    variable. The default behavior is to simply return:

    	'<div id="$id">\n' ~ get_html_children() ~ '</div>\n'

method WsfComponent.main();

    The main function for the task running this component. It is first
    called by the constructor and is running until it calls
    task_co_return().

    After that, get_html() is called by the WsfDocument object
    to create the HTML representation.

    The task_co_return() function returns when the user has done
    something in his browser window which effects this component; i.e.
    has clicked a link or submitted a form generated by get_html().

    Then this function can react to the event and call task_co_return()
    again when it has finished processing this event. Don't forget to
    set dirty to 1 if get_html() needs to be called again.

    If this method does not call task_co_return(), the task will hang
    in an endless loop. So don't forget to do that!

method WsfComponent.child_set(name, obj);

    Create (substitute) a child component.
    The 1st parameter is the key in the children array, the 2nd
    parameter the new component object.

method WsfComponent.child_remove(name);

    Remove a child component.
    The parameter is the key in the children array.

method WsfComponent.destroy();

    The destructor. It needs to be called when the object isn't needed
    anymore to kill the task assigned to that object. It also calls the
    destroy method of all child components.

    It is save to call that from the main() method. If you do so,
    killing the task is postponed until main() calls task_co_return()
    the next time. main() will then never return from this function
    again.

method WsfComponent.init();

    The constructor.

object WsfDocument

    The WsfDocument object. There must be one WsfDocument object for
    every browser window which is under control of WSF. Usually it
    is instanciated and assigned to a variable called 'page', then
    initialized and finally the main() method is called. E.g.:

    	var page = new WsfDocument();
    	page.title = "My Application Title";
    	page.root = new MyFunnyRootWsfComponent();
    	page.main();

    The main() method never returns.

static WsfDocument.domupdate = wsf_get_domupdate_status();

    This variable is automatically set when the module is loaded.
    It contains the return code of wsf_get_domupdate_status().

    It is possible to change that variable before instanciating
    WsfDocument the first time. After that, the variable shouldn't
    be touched anymore.

    Additionally it is possible to change that variable by passing
    a cgi query string parameter on program startup:

    	wsf_domupdate={ iframe | xmlhttprequest | none }

    If the domupdate mechanism is running in "iframe" mode,
    the iframe can be set visible by passing the query string
    parameter "wsf_showiframe".

    The "xmlhttprequest" method is probably the best implementation,
    but right now it is not possible to do file uploads using this
    method.

static WsfDocument.showiframe = 0;

    If domupdate is set to "iframe" and this variable is set to 1,
    the iframe used for the domupdate mechanism will be visible. This
    is only of interest for debugging purposes.

var WsfDocument.root;

    This is the root component for this WsfDocument. It must be set
    to an instance of WsfComponent (or any derived object) before
    the main() method is called.

var WsfDocument.title = "";

    The content for the <title> tag generated by this object. This
    can not be changed later, if domupdate is set to "iframe".
    So it must be set before calling main(), or not at all.

var WsfDocument.html_head = "";

    HTML code to be included between <head> and </head>.
    Must be set before calling main(), or not at all.

var WsfDocument.body_attr = "";

    HTML attributes to be set in the <body> tag.
    Must be set before calling main(), or not at all.

var WsfDocument.callbacks;

    A hash with arrays of callback functions. Use callback_add
    and callback_del to maintain the entries.

method WsfDocument.callback_add(type, func);

    Add a callback function to the callbacks data structure.

    The following callback types are called by this object:

    	pre_update	called before the html (xml) output is created.
    	post_update	called after the html (xml) output is created.

method WsfDocument.callback_del(type, func);

    Add a callback function from the callbacks data structure.

method WsfDocument.callback_call(type, %options);

    Call all callbacks of a type. The callback is passed the type as
    first parameter and this WfsDocument object as 2nd parameter.
    The named parameters are also passed thru to the callback functions.

method WsfDocument.main();

    This method implements the main loop of a WsfDocument.
    It must be called after setting up the variables described
    below.

    It handles the creation of HTML pages which are then passed
    to the browser. Whenever the WsfComponent.main() method
    calls task_co_return() after processing a user event, control
    is passed back to this method so it can update the browser window.

    This function does never return.

Generated by SPLDOC. | http://www.clifford.at/spl/