3. Lukas Renggli and Marcus Denker
ST — Seaside
5.3
Roadmap
> Introduction
— Web applications / Overview
— Installation
> Control Flow
> Components
> Composition
Original lecture notes by Lukas Renggli
4. Lukas Renggli and Marcus Denker
ST — Seaside
5.4
Roadmap
> Introduction
— Web applications / Overview
— Installation
> Control Flow
> Components
> Composition
5. Lukas Renggli and Marcus Denker
ST — Seaside
5.5
Introduction: Web Applications
Example: Adding two numbers
6. Lukas Renggli and Marcus Denker
ST — Seaside
5.6
What is going on?
<form action=“second.html”>
<input type=“text” name=“value1”>
<input type=“submit” name=“OK”>
</form>
<form action=“result.html”>
<input type=“hidden”
name=“value1” value=“<% value1 %>”>
</form>
<p>
<% value1 + value2 %>
</p>
first.html
second.html
result.html
7. Lukas Renggli and Marcus Denker
ST — Seaside
5.7
Control Flow:
HTTP request-response
User:
Web browser
first.html
second.html
GET first.html
<a href=”second.html?number1=...”
GET second.html?number1=...
<a href=”result.html?number1=...&number2=...”
8. Lukas Renggli and Marcus Denker
ST — Seaside
5.8
Something is wrong…
> Control-flow quite arcane
— Remember GOTO?
— We do not care about HTTP!
> How to debug that?
> And what about
— Back button?
— Copy of URL (second browser)?
9. Lukas Renggli and Marcus Denker
ST — Seaside
5.9
What we want
> Why not this?
go
|number1 number2 |
number1 := self request: ‘First Number’.
number2 := self request: ‘Second Number’.
self inform: ‘The result is ‘,
(number1 + number2) asString
10. Lukas Renggli and Marcus Denker
ST — Seaside
5.10
Seaside: Features
> Sessions as continuous piece of code
> XHTML/CSS building
> Callback based event model
> Composition and reuse
> Debugging and Development tools
11. Lukas Renggli and Marcus Denker
ST — Seaside
5.11
XHTML Building
html div id: ‘title’; with: ‘Title’
html div id: ‘list’; with: [
html span class: ‘item’; with: ‘Item 1’.
html span class: ‘item’; with: ‘Item 2’.
]
<div id=“title”>Title</div>
<div if=“list”>
<span class=“item”>Item 1</span>
<span class=“item”>Item 2</span>
</div>
12. Lukas Renggli and Marcus Denker
ST — Seaside
5.12
CSS
> CSS Zengarden: http://csszengarden.com
13. Lukas Renggli and Marcus Denker
ST — Seaside
5.13
Callback Event Model
Example3>>renderContentOn: html
html form: [
html submitButton
callback: [ self inform: ‘Hello’ ];
text: ‘Say Hello’ ]
....
<form action="/seaside/example2" method="post">
<input type="hidden" name="_s" value="JBbTXBnPaTLOjcjI" class="hidden"/>
<input type="hidden" name="_k" value="FFQrpnBg" class="hidden" />
<input type="submit" name="1" value="Say Hello" class="submit" />
</form>
....
14. Lukas Renggli and Marcus Denker
ST — Seaside
5.14
Composition + Reuse
Example:
Multicounter
More later!
21. Lukas Renggli and Marcus Denker
ST — Seaside
5.21
Seaside
http://localhost:8080/seaside
22. > Introduction
— Web applications / Overview
— Installation
> Control Flow
> Components
> Composition
Lukas Renggli and Marcus Denker
ST — Seaside
5.22
Roadmap
23. Lukas Renggli and Marcus Denker
ST — Seaside
5.23
2. Control Flow
> Defining control flow
> Convenience methods
> Call / Answer
> Transactions
24. Lukas Renggli and Marcus Denker
ST — Seaside
5.24
Defining Flow
> Create a subclass of WATask
— Implement the method #go
— Split the method #go into smaller parts to ensure readability
> Tasks are a special kind of component
— No visual representation
— Define a logical flow (#go)
— Call other components for output
25. Lukas Renggli and Marcus Denker
ST — Seaside
5.25
Convenience Methods
> #inform: aString
> #confirm: aString
> #request: aString
> #request:label:default:
> #chooseFrom:caption:
26. Lukas Renggli and Marcus Denker
ST — Seaside
5.26
Call and Answer
> #call: aComponent
— Transfer control to aComponent
> #answer: anObject
— anObject will be returned from #call:
— Receiving component will be removed
27. Lukas Renggli and Marcus Denker
ST — Seaside
5.27
Call and Answer
Client
aA
aB
aA
Server
A>>go
x := self call: B new.
x asString.
B>>go
…
self answer: 77.
A>>go
x := self call: B new.
x astring.
-> 77
28. Lukas Renggli and Marcus Denker
ST — Seaside
5.28
Transactions
> Sometimes it is required to prevent the user from going
back within a flow
> Calling #isolate: treats the flow defined in the block as a
transaction
> Users are able to move back and forth within the
transaction, but once completed, they cannot go back
anymore
29. Lukas Renggli and Marcus Denker
ST — Seaside
5.29
Example for #isolate:
self isolate: [
self doShopping.
self collectPaymentInfo].
Self showConfirmation.
30. > Introduction
— Web applications / Overview
— Installation
> Control Flow
> Components
> Composition
Lukas Renggli and Marcus Denker
ST — Seaside
5.30
Roadmap
31. Lukas Renggli and Marcus Denker
ST — Seaside
5.31
3. Components
> Rendering
— XHTML
— CSS
> Callbacks
— Anchor
— Form
> Customization
32. Lukas Renggli and Marcus Denker
ST — Seaside
5.32
Components
> Components are the Views (and Controllers) of Seaside
applications.
> Components keep their state (model and state of user-
interface) in instance-variables.
> Components define the visual appearance and handle
user interactions
33. Lukas Renggli and Marcus Denker
ST — Seaside
5.33
Building Components
> Components are created by subclassing WAComponent
> Add instance-variables to hold your model and user-
interface state
> Put view related methods in a category called rendering
> Put controller related methods into method categories
named accessing, actions, private
34. Lukas Renggli and Marcus Denker
ST — Seaside
5.34
Rendering
> XHTML is built programmatically.
> This process is called rendering.
> Create a method called #renderContentOn:
SomeComponent>>renderContentOn: html
html text: ‘Hello World’
35. Lukas Renggli and Marcus Denker
ST — Seaside
5.35
Text Rendering
> Render a string:
> Render an un-escaped string:
> Render any object (using double dispatch):
html text: ‘My Text’
html html: ‘<foo>Zork</foo>’
html render: 1
36. Lukas Renggli and Marcus Denker
ST — Seaside
5.36
Canvas and Brushes
> html parameter is instance of WARenderCanvas
— Basic html output
— Render logic
> Canvas provides brushes
— For rendering html tags
37. Lukas Renggli and Marcus Denker
ST — Seaside
5.37
Basic Brushes
> Render a new line <br />:
> Render a horizontal Rule <hr />:
> Render a non-breaking space :
html break.
html horizontalRule.
html space.
38. Lukas Renggli and Marcus Denker
ST — Seaside
5.38
Using Brushes
1. Ask the canvas for a div brush
2. Configure the brush, e.g. set attributes
3. Render the contents of the tag-brush:
html div.
html div class: ‘beautiful’.
html div
class: ‘beautiful’;
with: ‘Hello World’.
39. Lukas Renggli and Marcus Denker
ST — Seaside
5.39
Painting with Brushes
html div
html div
class: ‘beautiful’
html div
class: ‘beautiful’;
with: ‘Hello World’.
<div></div>
<div class=“beautiful”>
</div>
<div class=“beautiful”>
Hello World
</div>
Seaside XHTML
40. Lukas Renggli and Marcus Denker
ST — Seaside
5.40
Nesting Brushes
> Render a text in bold:
> Render a text in italic
> Render a text in bold and italic:
html strong with: ‘My Text’.
html emphasis with: ‘My Text’.
html strong with: [
html emphasis with: ‘My Text’].
41. Lukas Renggli and Marcus Denker
ST — Seaside
5.41
Nesting Brushes
> To nest brushes use the message #with:.
> Always send #with: as the last message in the
configuration cascade.
> The argument of #with: is rendered using double-
dispatch, therefore any object can be passed as an
argument.
> To nest tags, pass a block that renders the elements to
nest.
42. Lukas Renggli and Marcus Denker
ST — Seaside
5.42
Nesting Brushes
> Render nested divs:
> Render a list:
html div id: ‘frame’; with: [
html div id: ‘contents’; with: …
html div id: ‘sidebar’; with: … ].
html orderedList with: [
html listItem with: …
html listItem with: … ].
43. Lukas Renggli and Marcus Denker
ST — Seaside
5.43
Rendering Pitfalls I
> Don’t change the state of the application while
rendering, unless you have a really good reason to do
so.
> Rendering is a read-only phase.
> Don’t put all your rendering code into a single method.
Split it into small parts and choose a method name
following the pattern #render*On:
44. Lukas Renggli and Marcus Denker
ST — Seaside
5.44
Rendering Pitfalls II
> Rendering is a read-ony phase.
— Don’t send #renderContentOn: from your own code, use
#render: instead.
— Don’t send #call: and #answer: while rendering
> Always use #with: as the last message in the
configuration cascade of your brush
45. Lukas Renggli and Marcus Denker
ST — Seaside
5.45
Anchor Callback
> Ask the rendering canvas for an anchor and configure it
with a callback-block:
> The callback-block is cached and will be executed later.
html anchor
callback: [self someAction];
with: ‘Some Action’].
46. Lukas Renggli and Marcus Denker
ST — Seaside
5.46
Anchor Example
WACounter>>renderContentOn: html
html heading
level: 1;
with: self count.
html anchor
callback: [self increase];
with: ‘++’.
html space.
html anchor
callback: [self decrease];
with: ‘--’.
47. Lukas Renggli and Marcus Denker
ST — Seaside
5.47
Forms
> Render a form around your form elements:
> Put the Form elements inside the form:
html form: [
html textInput
value: text;
callback: [:value | text := value].
html submitButton ].
html form: [ … ]
48. Lukas Renggli and Marcus Denker
ST — Seaside
5.48
More Brushes with Callbacks..
> Text Input / Text Area
> Submit Button
> Check-Box
> Radio Group
> Select List
> File-Upload
Have a look at the functional tests!
49. Lukas Renggli and Marcus Denker
ST — Seaside
5.49
Register new Component / Task
> Create method #canBeRoot returning true on class
side
> Register using Seaside configuration interface.
> Or call #registerAsApplication: in the class-side
#initialize
50. > Introduction
— Web applications / Overview
— Installation
> Control Flow
> Components
> Composition
Lukas Renggli and Marcus Denker
ST — Seaside
5.50
Roadmap
51. Lukas Renggli and Marcus Denker
ST — Seaside
5.51
4. Compositon
> Backtracking
> Subcomponents
> Widgets
52. Lukas Renggli and Marcus Denker
ST — Seaside
5.52
Backtracking State
> Seaside does not backtrack state by default.
> Often it is not obvious whether an object should be
backtracked or not. Mostly this has to be decided by the
developer on a per-object basis.
> Any object can be declared to be backtracked.
53. Lukas Renggli and Marcus Denker
ST — Seaside
5.53
Shopping Cart Problem
> Online Bookstore (without backtracking)
— When using the back-button, usually the items should not be
removed from the cart; just resume browsing from the old
location.
> Flight Reservation System (with backtracking)
— When using the back-button, usually you want to check other
flights, this means the selected flight should be removed.
54. Lukas Renggli and Marcus Denker
ST — Seaside
5.54
Register Object
> Implement method #states that returns an Array that
contains your object.
> This will backtrack the instance-variables of the objects,
not the objects themselves
SomeComponent>>#states
^ Array with: model.
55. Lukas Renggli and Marcus Denker
ST — Seaside
5.55
Subcomponents
> It is common for a component to display instances of
other components.
> Components can be nested into each other using the
composite pattern.
> A subcomponent is displayed using the method
#render: on the canvas.
56. Lukas Renggli and Marcus Denker
ST — Seaside
5.56
Initialize Children
> Subcomponents are usually stored within instance
variables of the parent component.
> Subcomponents are commonly created lazily or as part
of the components #initialize method.
SomeComponent>>initialize
super initialize.
counter := WACounter new.
57. Lukas Renggli and Marcus Denker
ST — Seaside
5.57
Enable Children
> Parent Components must implement a #children
method returning a collection of subcomponents that
they might display.
> If you fail to specify #children correctly, Seaside will
raise an exception.
SomeComponent>>children
^ Array with: counter
58. Lukas Renggli and Marcus Denker
ST — Seaside
5.58
Render Children
> Children are rendered by sending the message
#render: to the rendering canvas.
> Never directly send #renderContentOn: to the
subcomponent.
SomeComponent>>renderContentOn: html
html heading level: 1; with: ‘My Counter’.
html render: counter.
59. Lukas Renggli and Marcus Denker
ST — Seaside
5.59
Widgets
> Components can be reused in different contexts within
different applications.
> Seaside is shipped with a small collection of widgets
ready to use.
> Load and use widgets that have been developed by the
Seaside community.
> Write your own widgets that exactly fit your needs
60. Widgets: Examples
Lukas Renggli and Marcus Denker
ST — Seaside
5.60
Have a look at the classes in
Seaside-Components-Widgets
Batched List
Tab Panel
Calendar
61. Lukas Renggli and Marcus Denker
ST — Seaside
5.61
Custom Widgets
> Create a new component.
> Add methods to specify domain-model, subcomponents,
properties…
> Assign CSS names/classes to make it skinnable with
css style-sheet.
— Implement method #style to return CSS for component
> Write tests and small example applications.
62. Lukas Renggli and Marcus Denker
ST — Seaside
5.62
There is more..
> Development Tools
— Demo in the Exercise Session (Halo, Configuration…)
— Debugging: Next Lecture
> Javascript: Prototype, script.aculo.us, jQuery, jQueryUI
> Persistency (Databases)
64. Lukas Renggli and Marcus Denker
ST — Seaside
5.64
Literature
> Dynamic Web Development with Seaside
— http://book.seaside.st/book
> HPI Seaside Tutorial:
— http://www.swa.hpi.uni-potsdam.de/seaside/tutorial
> Articles:
— “Seaside — a Multiple Control Flow Web Application Framework.”
— “Seaside: A Flexible Environment for Building Dynamic Web
Applications”
— http://scg.unibe.ch/scgbib?query=seaside-article
> …. more at http://seaside.st