Intro#
This document is meant for designers working as part of a team that is building a web application that uses RSF for its presentation layer. It assumes comfort with HTML, CSS, file systems, Dreamweaver a plus. It assumes that the initial "design" is pretty much set and deals mostly with the mechanics on how to produce RSF templates that will make your colleagues smile.
To keep it simple - only markup will be dealt with - no behaviours, AJAX, etc.
- First part will explain how things work, best practices.
- Second part will go over creating templates with Dreamweaver and a Dreamweaver library. This last part is focused mainly on Sakai rendering idioms.
- Third and last will aggregate tips, ruminations, notes on aspects of the whole process.
1 - Working with RSF #
RSF is a pure HTML templating system. This means that the markup you create ends up being the bones of the presentation layer of the application - putting you in total control of it.
Lets take a look at an example. This is a simple table that you can preview in the browser. You have written it, populated it with plausible content, tested it with users, edited it, etc. The only odd thing about it is the rsf:id attributes. These have the following purposes:
Line 7: <span rsf:id="headertitle1">Header title 1</span> - this is a leaf node. The value inside the <span /> will be substituted by a value determined by the rsf:id
Line 15: <tr rsf:id="row:"> - this is a branch, in this case indicating an iteration - the values of the children will be determined by the branch logic - it will cycle through all the items this table represents, and determine for the first cell/img if there is an attachment involved (and render a paperclip), for the second cell/span the name of the item (and render that), for the last cell/a if the user has the right to edit it (in which case she will get a link).
And that is it. There are some subtleties but we will cover these later.
- <table rsf:id="tableFlat:" class="tableFlat" summary="Descriptive data table summary">
- <caption rsf:id="caption">Caption</caption>
- <thead>
- <tr>
- <th class="attach" id="attach"> </th>
- <th id="id1">
- <span rsf:id="headertitle1">Header title 1</span>
- </th>
- <th id="id2">
- <span rsf:id="headertitle2">Header title 2</span>
- </th>
- </tr>
- </thead>
- <tbody>
- <tr rsf:id="row:">
- <td headers="attach" class="attach">
- <img rsf:id="paperclip" src="library/images/sakai/attachments.gif" alt="Attachments" />
- </td>
- <td headers="id1">
- <span rsf:id="cellcontents">Cell contents</span>
- </td>
- <td headers="id2">
- <a rsf:id="item-modify" href="modify.html">Edit</a>
- </td>
- </tr>
- <tr rsf:id="row:">
- <td headers="attach" class="attach">
- <img rsf:id="paperclip" src="library/images/sakai/attachments.gif" alt="Attachments" />
- </td>
- <td headers="id1">
- <span rsf:id="cellcontents">Cell contents</span>
- </td>
- <td headers="id2">
- <a rsf:id="item-modify" href="modify.html">Edit</a>
- </td>
- </tr>
- <tr rsf:id="row:">
- <td headers="attach" class="attach">
- <img rsf:id="rsf-id-paperclip" src="library/images/sakai/attachments.gif" alt="Attachments" />
- </td>
- <td headers="id1">
- <span rsf:id="cellcontents">Cell contents</span>
- </td>
- <td headers="id2">
- <a rsf:id="item-modify" href="modify.html">Edit</a>
- </td>
- </tr>
- </tbody>
- </table>
Recommended procedures#
Regardless of how you create your markup - here are some guidelines:
write them as you see them #
Write your template so as to account for all the possible variables once it is running in the application. Although a table only needs one row (<tr>) branch to run correctly (iterate over all the members of the list and create as many rows, for example), you might want to put in 10 of them to see how it looks. The application will ignore the extras but having your template fully populated will help you visualize it.
comment lavishly#
Despite the fact that RSF templates are pretty much the presentation layer of the application, comments are needed to provide guidance to the developers. You might want to add an identifying word to your comments so that you can remove them after a testing phase is complete. Comment everything, early and often!
For example. Assume that a view has a table. If there are no items you do not want any part of the table to show. Instead you want to render a status message. Comments will help developers make sure that is what happens:
- <!-- designNote: message below gets rendered if there are no items for tableFlat:-->
- <p rsf:id="emptylistmessage" class="messageInstruction">A helpful status message</p>
- <!-- designNote: table below only gets rendered if there is one item or more -->
- <table rsf:id="tableFlat:" class="tableFlat" summary="Descriptive data table summary">
- . . . . . . .
- </table>
use real links#
- <a rsf:id="add_new_item" href="add_new_item.html" >Add new item </p>
using rsf:ids #
This is a bit more complex. In fact - you might negotiate with the developers that you will not be adding rsf:ids at all. They will rely on your lavish comments and your crystal clear documentation to figure these out. If this is so - comment! And if you are using the Dreamweaver library - remove all the stub rsf:ids from the templates.
But if not - here are some guidelines.
- Put rsf-id first: make the rsf:id the first attribute of the element - this helps developers scan your template
- Be meaningful: give the rsf:id a meaningful name that presages what should happen when the producer gets ahold of it and the nature of whatever gets sent to the browser.
- Be consistent: stick to the same naming convention for rsf:ids (another negotiation with developers might be needed here: camelCase, under_score, dash-madness, etc.).
- Be logical: make rsf:id reflect the logic of the view -
A leaf represents just a one to one value.
- Be prepared: think of your page as an application with dynamic content and behaviours. If you take a look at the markup for the table above you will notice:
- <td headers="id1">
- <span rsf:id="cellcontents">Cell contents</span>
- </td>
- Be multilingual: Add all values of rsf:ids that resolve to literals to a myappname.properties file - this is icing on the cake and will really help when you localize your application for other languages and make the language of your application consistent.
So - for example, the markup
- <h3 rsf:id="msg=page_title">A title </h3>
Means that the application will look up myappname.properties (sample below) the value of "page_title" and use it to substitute the words "A title" with "A title", "Un tÃtulo", "Un titre" etc., depending on the language of the user.
- page_title=A title
- table_caption=Table caption
- table_subject_header=Subject
- . . . . . . . .
("common" below should have a hashmark octothorpe pound sign to denote it is a comment - but in this wiki it is used to denote a list item)
common
item=Item
save=Save
cancel=Cancel
edit=Edit
. . . . . . . .
("list of items view" below should have a hashmark octothorpe pound sign to denote it is a comment - but in this wiki it is used to denote a list item)
list of items view
page_title=List of items
table_caption=List items. Column 1 indicates if there is an attachment, column 2 the item name, column 3 a link to edit item if allowed.
table_subject_header=Subject
. . . . . . . .
("edit item view" below should have a hashmark octothorpe pound sign to denote it is a comment - but in this wiki it is used to denote a list item)
edit item view
subject_input_label=Subject
. . . . . . . .
Note: if your strings are complex - that is - they consist of a literal and a variable - use a normal rsf:id and make sure that the comments and the model reflect this.
For example:
- <!-- designNote: notice the model below for rsf:id value -->
- <p rsf:id="view_x_of_y" class="instructionMessage instruction">Viewing 1-10 of 34 messages</p>
Format well#
Keeping to a consistent format for indentation will keep you and the developers from running melancholy mad, specially when things get complicated. Dreamweaver does this decently - it looks like: Command/Apply Source Formatting
Make well formed and valid#
Make sure it is well formed and valid XHTML. This will:
- allow it to work as a template at all!
- allow you to pinpoint rendering problems as browser deviations from the norm
- make you feel very virtuous
2 - Creating the pages with Dreamweaver #
Setting up#
If you want to use the Dreamweaver library and snippet collection:- Download and unpack the library
- Put Sakai snippets folder into snippet library - this will depend on system.
For Windows, it will be in: E:\Documents and Settings\(username)\Application Data\Macromedia\Dreamweaver 8\Configuration\Snippets
For OSX it will be: /Applications/Adobe Dreamweaver CS3/Configuration/Snippets
- Put site stub (templates, CSS, javascript) where you keep these things. If you are reading this you already know more about Dreamweaver than I do, so you probably know where.
Doing it#
Again - it is assumed the initial design is done. The flow/navigation has been defined, the views sketched out a grosso modo. The sequence follows:
- Designate a default view - this may be the initial view of the application, given the role and any other contextual information that applies.
- Create a new page for this default view. If you are using the DW library this will be based on the sakai-generic.dwt template. This will create a stub with the right declarations and links to css files and so forth. The part you will add markup to will be:
- <body>
- <div class="portletBody">
- - - - - - here! - - - - -
- </div>
- </body>
- Save this page - giving it a very descriptive name
- Start dragging and dropping elements of the clip library as needed into your page. Working in code view will give you better results as you will know exactly where you are dropping things.
As an example the page will have:
- a menu so that people can navigate to a different view
- a menu so that people can select actions to perform in the current view
- a list where each item has 3 attributes, as well as a set of possible actions on each item
- navToolBar
- actionToolBar
- tableFlat
Each element will provide all the markup needed. Let's take a look.
The navigation toolbar (navToolBar)#
- <ul rsf:id="navToolBar:" class="navToolBar">
- <li rsf:id="rsf-id-stub:">
- <a rsf:id="rsf-id-stub" href="#" title="title">Go somewhere</a>
- <li rsf:id="rsf-id-stub:">
- <a rsf:id="rsf-id-stub" href="#" title="title">Go there</a>
- <li rsf:id="disabled" class="disabled">Disabled Destination
- <li rsf:id="current" class="current">You are here
- </ul>
The snippet assumes that the navigation toolbar should be a branch. The producer will generate everything inside of it. In this case your markup is two things: 1) a placeholder - something that allows you to preview how it will look, do some user testing, etc, and 2) an indication to the developers of what should be sent to the browser.
Here are the edits I would do on this generic snippet:
- Change all the list items and links (and their attributes) to something that will make sense in this view in this application.
- Remove all the rsf:ids that do not have a corresponding value
- Change all the rsf:ids to something meaningful (this will help the developer)
- Change the href attribute values so that the link is pointing at another template that represents what would happen when application is running. The "Edit this thing" link should point to "edit-thing.html" template, for example (this will help everyone)
The action toolbar presents the same set of choices, so will not deal with it, but here it is:
The action toolbar (actionToolBar)#
- <ul rsf:id="actionToolBar:" class="actionToolBar">
- <li rsf:id="rsf-id-stub:">
- <a rsf:id="rsf-id-stub" href="#" title="title">Add New Item</a>
- <li rsf:id="rsf-id-stub:">
- <a rsf:id="rsf-id-stub" href="#" title="title">Add New folder</a>
- <li rsf:id="disabled" class="disabled">Disabled Action
- <li rsf:id="current" class="current">Current Action
- </ul>
a list (tableFlat)#
- <table rsf:id="tableFlat:" class="tableFlat" cellpadding="0" cellspacing="0" summary="Descriptive data table summary">
- <caption rsf:id="rsf-id-stub" title="a title">
- Caption
- </caption>
- <thead rsf:id="rsf-id-stub">
- <tr rsf:id="rsf-id-stub:">
- <th rsf:id="attach" id="attach" class="attach"> </th>
- <th rsf:id="id1:" id="id1">
- <a rsf:id="rsf-id-stub:" href="#" title="title">
- <img rsf:id="rsf-id-stub" src="library/images/sakai/sortascending.gif" alt="alt" border="0" width="11" height="11"/>
- Header title
- </a>
- </th>
- <th rsf:id="id2:" id="id2">
- <a rsf:id="rsf-id-stub:" href="#" title="title">
- <img rsf:id="rsf-id-stub" src="library/images/sakai/sortascending.gif" alt="alt" border="0" width="11" height="11"/>
- Header title
- </a>
- </th>
- </tr>
- </thead>
- <tbody rsf:id="rsf-id-stub">
- <tr rsf:id="rsf-id-stub:">
- <td rsf:id="attach" headers="attach" class="attach"></td>
- <td rsf:id="rsf-id-stub:" headers="id1">
- <a rsf:id="rsf-id-stub" href="edit-thing.html" title="title"> Edit this thing</a>
- </td>
- <td rsf:id="rsf-id-stub" headers="id2">Cell contents</td>
- </tr>
- </tbody>
- </table>
The markup above should be familiar - I have cut all data rows but one (all the backend producer needs in any case). Edits I would do:
- Add/substract columns as needed
- Edit the content - make it meaningful for the template as a standalone.
- Change all the list items and links (and their attributes) to something that will make sense in this view in this application.
- Make all ids unique
- Change all the rsf:ids to something meaningful (this will help the developer)
- Change the href attribute values so that the link is pointing at another template that represents what would happen when application is running. The "Edit this thing" link should point to "edit-thing.html" template, for example (this will help everyone)
Adjusting the markup#
Notice that the snippets include a lot of attribute placeholders. In the table above you will see a summary, a caption, header id and cell headers. The images have alt. The only placeholder attributes included in the snippets are the ones required to create minimally meaningful markup (mmm!) - there are many other possible attributes - these are your call and will depend on the context. For example: in a long list that repeats the "Edit" link - it could be argued that the <a> should include a title attribute that incorporates the name of the thing being edited, making each link distinct. Thus:
- <a rsf:id="item-modify" href="modify.html" title="Edit (item name)" >Edit</a>
Previewing it #
Save your file and preview in a browser. Now may also be a good time to apply formatting, validate.
More....#
Process#
I found myself following this process when building templates. This might work for you as well:
- Create stub template on the basis of sakai-generic DW template
- Populate with the snippets, in code view so I could see what I was doing
- Adjust the content of the template in design view
- Adjust the markup (non visible attributes, rsf:ids, comments, etc.) in code view
- Apply source formatting
- Preview and validate
On style#
Since the template links to external CSS files reference the files in the location where these in the Dreaweaver site, and will change to reference the location of the same in the server, this is going to really cramp your style once past the first iteration, as you will be getting the templates back with the new path.
You can ask that the <link /> elements be rsf:id'd. Then they will change from
- <link href="/library/skin/tool_base.css" type="text/css" rel="stylesheet" media="all" />
- <link href="/library/skin/default/tool.css" type="text/css" rel="stylesheet" media="all" />
- <link href="library/skin/tool_base.css" rsf:id="scr=portal-matter" type="text/css" rel="stylesheet" media="all" />
- <link href="library/skin/default/tool.css" rsf:id="scr=portal-matter" type="text/css" rel="stylesheet" media="all" />
Doing Demos/Testing with your RSF templates#
You will probably want to use the same set of files to do testing and demos as you are using for the templates. A given single template will work to present complex flows - some parts will be rendered, others not, for example, or a list will be sorted with a click, etc. How to replicate this behaviour in static files?
One solution is to add this to the template with javascript. A better one is to duplicate the template, edit the new one to display the change and save it with the suffix "-demo" as well as edit the old one and create a link to the new one. The workflow will work (for demos and testing) and the developers will then know that this is an interim template that should be ignored.
See: this example - click on the "Search" button and you will get UBookBookAddbyISBN-d.html - which is the for demo variant of what the original template (UBookBookAddbyISBN.html) will do once it is running (the extras provided by UBookBookAddbyISBN-d.html also are in UBookBookAddbyISBN.html but commented out).