File: README.WEBSPL

package info (click to toggle)
spl 1.0~pre2-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,240 kB
  • ctags: 1,987
  • sloc: ansic: 15,272; yacc: 3,167; sh: 272; makefile: 186; xml: 156
file content (251 lines) | stat: -rw-r--r-- 11,072 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

WebSPL and WSF Tutorial
=======================

This is a short tutorial to WebSPL and WSF. It is not a reference manual, so
also have a look at the "wsf" module, the "cgi" module and related modules in
the module references.

If you have not yet set up your Web Server to handle webspl scripts, please
have a look at the README file or the 'What is SPL?' chapter in this manual.


WebSPL Introduction
-------------------

WebSPL is an SPL runtime for CGI programming. There are two implementations
of WebSPL: The CGI script "webspl.cgi", for integrating WebSPL with the
Apache webserver using an 'action-handler', and "webspld", a stand-alone HTTP
server.

The SPL sources inlcude an example "httpd.conf" file for using "webspl.cgi"
with the Apache webserver. The "webspld" program prints its own usage info
when called with '--help'.

The interesting thing about WebSPL is, that, other than usual CGI scripts, a
WebSPL script is not executed once for each HTTP request. Instead, there is
just one (virtual) SPL process for a session and the WebSPL script can pause
it's execution at any time, wait for the user to do something and continue
execution as soon as the webbrowser sends the next HTTP request for the
session.

This is a tutorial - so here is our first example program:

	/* -- webspltut/webspltut00.webspl -- */

Whenever task_pause() is called, the program execution stops and what has
been written since the last task_pause() (or the beginning of the program
execution) is displayed in the web browser.

As soon as the user reacts (i.e. clicks on "next" in this example), the
execution of the program is continued and task_pause() returns. The query
string parameter 'sid' is special: It always contains the session id and must
not be used for anything else in WebSPL applications. If the script is using
SPL tasks, it is also possible to include the ID of the task which should be
woken up in the 'sid' parameter. E.g. WSF is doing that.


WSF Introduction
----------------

WSF (WebSPL Forms) is a library for doing web application development with
WebSPL. WSF provides a widget based interface and so allows the development
of web applications with a look&feel like normal GUI programs. But it is
a bad choice for creating dynamic webpages since example given the browser
back button must not be used in WSF applications. For this (and other)
reasons it is recommended to open WSF applications in browser popup windows
without browser toolbars.

There are two base classes in WSF: WsfComponent and WsfDocument.

The WsfDocument object handles a browser window. Usually there is only one
instance of that object in a program, but if you want to use WSF to manage
multiple windows, one WsfDocument instance per browser window is required.
This WsfDocument instance is usually (i.e. per convention, there is no
technical reason for doing so) assigned to a global variable named "page".

The content of a browser window is organised as a tree of WsfComponent objects.
The root component must be assigned to the "root" member variable of the
"page" object. The WsfComponent object itself has a member variable called
"children" which is an array/hash of the child components.

In most cases objects derived from WsfComponent are used instead of
WsfComponent directly. One of these derived objects is WsfDisplay from
the "wsf_display" module (WsfDocument and WsfComponent are declared in
the "wsf" module).

The HTML text which should be displayed in a WsfDisplay object is simply
passed to the constructor. So here is a very simple WSF "Hello World"
application:

	/* -- webspltut/webspltut01.webspl -- */

The page.main() does never return.

The default behavior of the WsfComponent object is to simply print the html
content of all its children in its get_html() method. So it is pretty useful
as a simple container for other more complex objects derived from WsfComponent:

	/* -- webspltut/webspltut02.webspl -- */

But this application doesn't do much. So, lets create our own object derived
from WsfComponent which implements a simple counter:

	/* -- webspltut/webspltut03.webspl -- */

So, when creating your own WSF Components, you need to overload the get_html()
method with something which returns the HTML code for your component and
overload the main() method with the main program for the task managing this
component. The task executing the main() method is created automatically by
the object constructor (and killed by the destroy() method). The function
task_co_return() must be called by main() to wait for user events. The variable
'dirty' must be set to 1 when anything happend with an effect on the get_html()
output. The root element of the HTML code generated by get_html() must have its
'id' attribute set to the value of the 'id' variable. There are methods (such as
the add_href() used in the example) for creating links, formulas, etc.

Have a look at the module reference for the "wsf" module for a full overview
of the WsfDocument and the WsfComponent objects.


Adding Menus
~~~~~~~~~~~~

Applications always have some type of menu. There is a generic WSF component
called WsfMenu (from the "wsf_menu" module) which implements nice menus. The
menu entries are function pointers which are called when the entry has been
clicked:

	/* -- webspltut/webspltut04.webspl -- */

The HTML code generated by WsfMenu should be the first real code in the
webpage. So the example is using a simple WsfComponent as root component and
WsfMenu as its first child (0). The 2nd child (1) is set to WsfDisplay objects
by the menu callbacks to display messages.


Example Application: A very simple CMS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now lets write a real application: a very simple CMS. Don't expect too much:
It is not much more than just a web-based file manager for HTML files. Do not
wonder: the login for the login screen is covered in the next section.

	/* -- webspltut/webspltut05.webspl -- */

Please run the application before you continue reading this tutorial (just to
make sure you know what this is all about).


The application defines two Objects: Editpage for dialog which lets the user
edit a page and Newpage for the dialog which lets the user create new pages.

The application also defines the function create_menu() for (re-)creating the
menu.

The main program just creates the page object, the root component, calls
create_menu() and enters page.main().


The create_menu() function
..........................

This function creates the menu as child component of the root component. The
"Pages" menu is dynamically generated from the list of *.html files in the
current directory. Whenever files are added or removed, create_menu() must be
called in order to update this menu.

A closure is used to store the filename to be opened together with the callback
function which is called when an entry in the "Pages" menu is clicked.


The Editpage Object
...................

Editpage is directly dervied from WsfComponent. The filename of the file to be
edited is passed as an argument to the constructor and copied to the variable
'filename' there. The methods get_html() and main() are overloaded.

The get_html() method simply displays an HTML form for editing the page. The
page content is loaded from the HTML file. Note how the 'xml::' and 'js::'
encoding functions are used to ensure the correctness of the generated HTML
code.

The main() method simply writes back the data to the file, or removes the file
if the user clicked on the "Remove" button. Since main() is automatically
called in an endless-loop, I did not add the "while (1) { ... }" loop here
explicitly. When main() is removing the file, the menu is updated by calling
create_menu() and the Editpage component is replacing itself with a simple
WsfComponent instance.


The Newpage Object
..................

The Newpage opject (also directly dervied from WsfComponent) is even simpler.
get_html() just displays an HTML form again. When the form is submitted and
main() returns from task_co_return(), it simply creates the new page (after
cleaning up the filename), calls create_menu() and replaces itself with an
Editpage instance for the newly created file.

Note that a Here-Document with indenting character is used when creating the
HTML text for the new page. This avoids ugly leading blanks in the HTML file
while keeping the indenting in the program intact.


Login screen and opening a popup window
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The last example is using a pretty nice mechanism for doing authentication and
opening a popup window. Before creating the 'page' object and passing control
to WSF, this code is executed:

	/* -- webspltut/webspltut06.spl -- */

There is nothing wrong with already accepting parameters at program startup.
The program expects username and password in the query string parameters "user"
and "pass". If they are not present or wrong, the login screen will be printed
and the program exits.

Only if correct authentication tokens are passed, the program continues
execution and initializes the WSF framework. It has shown that this approach is
very useful and much easier than actually including this step in the
application itself. One of the benefits of this approach is that a developer
can pass the authentication tokens already in the query string and so bypass
the additional screen. That's very comfortable for testing the application
during the development. Some applications even allow 'deep-linking' to some
dialogs this way to make testing easier. This approach also allows to open the
application in a popup window easily.

Opening a popup window makes sense since we do not want the user to click on
the browser 'back' button or bookmark any deep links of the application. It
doesn't really prevent the user from doing such stuff - but it makes it hard
enough to avoid most of the troubles.

Opening the popup window is simply done by printing the javascript code and
then calling task_pause(). As soon as the the browser tries to load the content
of the popup window, the session is resumed and task_pause() returns.


W2T Introduction
----------------

The W2T (Web 2.0 Toolkit) module provides another framework for web application
development. W2T applications only send an initial XML document (usually XHTML
or SVG) to the browser and everything after is done using AJAX XML RPC calls.

The W2T module is basically a collection of SPL and JavaScript functions which
provide functionality for updating the XML DOM tree displayed in the browser
window from server-side SPL and call server-side SPL event callbacks from
browser-side JavaScript code.

Here is a small W2T example program which is using SVG. Note that at the time
of this writing Firefox 1.5 is the only browser which can be used as frontend
for W2T SVG programs:

	/* -- webspl_demo/w2tdemo_svg.webspl -- */

The W2T module also includes some JavaScript helper functions for doing
animations and other funny stuff. W2T is under development and a more detailed
documentation will be provided when it is finished.