Hello! In this sequence, we'll learn more about Seaside,
especially the part that generates HTML.
You recall that all Seaside components
respond to "renderContentOn" messages.
This message is what enables us to generate the appropriate HTML code.
This method has a parameter named HTML.
It is an object instance of the WAHtmlCanvas class or subclass.
It is dedicated, offering the programmer an API to generate valid HTML.
Our counter code is here.
The html object here is used to generate headings, anchors, spaces, etc.
Today's sequence goes further into this language.
The dedicated language is made up of "brushes."
Each brush is dedicated to generating a particular HTML tag.
The API is object-oriented.
Its very construction, using message-sending to objects,
guarantees the validity of the HTML code,
unless we have made a messaging error.
Here's an example, using the dedicated language.
I send the html object the message "div"
which will render one object.
This object is a brush dedicated to generating
html div codes.
It includes the "id" message,
and the message "with."
This generates a div with the attribute id = title.
The character string identified as Title will be part of the div.
I can generate more complex things.
The beginning is the same: html div id list.
This is my div line.
But I can put lots of other tags inside the div.
Instead of sending a character string to "with," I send a script.
Within that script, I can reuse my html object
and other brushes to generate other tags.
With "html span class item"
I generate a span with a class attribute and content.
Now I can use loops.
This DSL is as powerful as Pharo.
Here, I generate an unorderedList.
It's abbreviated "ul."
It has an id list attribute.
I have list items inside the unordered list.
They are here.
Only I generated them using a loop.
I have a "to do 1 to 5" loop.
A classic Pharo loop. I generate 5 list items
with an attribute class... item...
followed by the name of each list item.
I have concatenated the loop cursor.
Item 1, Item 2, Item 3, etc.
We can go one notch farther,
and code for a different class selector CSS
for each list item,
depending on an odd or even loop cursor.
Typically, here, for example, I use the message .class: if:
That means "add this class if the following condition is true."
Here's the one for "even."
You can see that in the generated code, the first list item
has this particular class CSS.
"itemodd."
The second item has this CSS class: even.
This one is even, this one is odd, etc., etc.
The syntax is concise.
It packs all the power of Pharo to generate HTML using a DSL.
Another feature of this dedicated language
is extensibility.
It is easy to make it support modern CSS frameworks
like Bootstrap, for example.
This CSS framework uses CSS classes
to generate attractive HTML elements,
like green or blue backgrounds, etc.
How do we go about extending the dedicated language?
We have special brushes like the one here.
They all have a "tbs" prefix, meaning "twitter bootstrap."
I send the message "tbsAlert" to my HTML object.
That means "generate an HTML div or element
"compliant with the Twitter Bootstrap framework."
Many brushes will refer to the TBS framework.
I can render Twitter buttons with "tbsButton."
And TBS button groups, this way.
You can see that these three buttons all belong to one group.
To return to the example of the counter, from last session:
We defined a simple counter.
Now I'll make a Twitter Bootstrap version of it.
It's very easy. I make a subclass of my earlier counter,
called "WATwitterCounter."
I go to the "class" side
of this class
and define the method "initialize," which specifies:
"this component will be using the TBS development library."
Here is TBSDevelopmentLibrary and JQDevelopmentLibrary.
Those are Javascript and CSS frameworks.
Next, I'll return to the instance side of this class.
I'll define a new renderContentOn method,
redefining the preceding one.
All my brushes will begin with tbs.
"tbsButtonGroup," "tbsButton," etc., etc.
But this doesn't change my regular code,
still consisting of callbacks with "self increase"
and "self decrease."
It doesn't change a thing.
The only parts that use TBS are the HTML rendering brushes.
Now we'll see what my new counter looks like.
The plus and minus buttons are together in my Button Group.
And counter value is displayed on a badge,
in this Bootstrap version.
You can go even farther, beyond Bootstrap.
You can define your own style rules.
For example, here, I decided to say
that I want all "odd" elements
to be in the "odd" class.
Every time I render the counter value here, as a TBS badge...
That is, the counter value will be displayed...
But I'm adding the CSS class "odd"
only if the value is odd.
The CSS class is added only if this condition is true.
I defined the CSS class "odd"
by defining the method "style" on my counter.
It will render a character string according to CSS style rules.
".odd color: red" will make the counter red
for odd numbers.
To sum up:
A web application is a root component. Seaside is a root component.
All components can be rendered in HTML using renderContentOn.
And we have a dedicated language that is powerful and extensible.
It enables us to generate HTML easily, using brushes,
and an extensibility that supports existing CSS frameworks
like Bootstrap, JQuery, UI, etc.
You can take advantage of Pharo's scripting powers like loops,
to generate arrays of elements easily.