Yellow is an engine for web sites in which every page has a next and a back button, so that the visiting user can traverse the pages forwards and backwards, like the pages in a book. On each page the user can enter data. The passage through the pages needn't be a linear sequence: it can contain conditional bifurcations and loops, controlled by the entered data.
Such a web site is modelled as a javascript program that will be executed on the server. The program defines the construction and order of the pages. Each single page is read from a template, and may be modified before rendering.
The directory of source files that together make up a yellow web is called a "story".
The main file is the javascript definition of the story. It is identified by having the same name as the story.
The story may also contain html templates that can be read by
var d=new Document(path)
.
The story may also contain static files that are referenced by the documents, for example CSS and client-side javascript. They may be at top level or in sub-directories.
Here is an example, a story called "survey":
survey/
survey.js
--must be here and have same name as story
first.html
--template with relative links to static files
second.html
third.html
css/
basic.css
mobile.css
img/
logo.jpg
face.jpg
js/
magic.js
The story is requested from the browser under this URL:
http://www.yellow.cat/stories/space/survey/
The prefix http://www.yellow.cat/stories/space/
depends on the
yellow installation and is not relevant in this reference document.
The suffix survey/
identifies the story by name. The trailing / means:
find the javascript program survey.js
and execute it, producing
an html document. That document can have relative links to the static
files in the directory, like http://www.yellow.cat/stories/space/survey/css/basic.css
.
The language of the programs is ECMAScript (ECMA-262 3rd edition).
Additionally, there are these features:
Document
| server-side representation of a HTML document, with methods as in DOM level 3 Core |
new Document()
| makes a simple document with buttons for next and back. |
new Document(path)
| makes a document by parsing a template. The path is relative to the program file. |
//d is a Document
| interrupts javascript execution and sends the document to the browser. |
redirect(url)
| terminates program execution and redirects the browser to url. Sends 303 See other redirection. |
session["name"] = "Alex"
|
Attributes in the session scope are not set to old values
by backwards navigation.
|
When the yellow engine sends a document to the browser, it inserts these javascript functions:
next()
| continues javascript execution until the next document. |
back()
| jumps back to the previous document. |
The document author can use these functions in designing a UI for next/back.
A simple UI would be:
<button onclick='next()'>></button>
which looks like this:
The next()
function continues javascript execution on the server until
the next document.show()
and then show that document in the browser.
If execution reaches a redirect(url)
the browser will show that URL.
If execution reaches the end of the program ... that's an error, the program is bad.
The back()
function jumps back to the previous document.
If there is no previous document ... that's an error, the program is bad.
Jumping back means all the javascript variables will go back to the values
they had previously (except the scope session
).
Yellow sends a document to the browser as html text. Let's call converting a document object to this text "rendering".
Rendering treats these elements and attributes in a special way:
<div data-for-x="expression" >...</div>
| If an element has an attribute that starts with data-for-, then that element will be repeated zero or more times. The end of the attribute key will be taken as a variable, for example, data-for-x generates the variable x. The value of the attribute is a javascript expression. It will be evaluated and should yield an array (or similar). The element will be repeated once for every element in the array, bound to the variable. |
<div data-if="expression" >...</div>
| The value is a javascript expression. Its result should be a boolean. If the result is true, the element will appear once. If the result is false, the element will not appear. |
<div data-var-x="expression" >...</div>
| Sets a javascript variable, only for the rendering of this element. The last part of the attribute key, after data-var- will be taken as variable name. The value is a javascript expression. Only for the rendering of this element, the variable will have the result of the expression. Afterwards, it will again have whatever value it had before. |
<div data-substitute="path" >...</div>
| The value is path to a file that contains partial html. The path is relative to the this template. The document will be parsed and rendered, and its resulting root element will be inserted into this document, substituting the element with the attribute. |
${expression}
| A $-expression can appear inside an element or inside an element attribute value. The expression cannot appear in an element tag name nor in an attribute key. The expression is a javascript expression. The expression is evaluated and rendered in the document. If the expression is in an element, the result is escaped in order to prevent html and javascript injection. If the expression is in an attribute value, the result is escaped adequately. |
<input disabled="${expression}" >
|
Many html-elements have boolean attributes, for example the input-element has
a disabled-attribute, which is boolean.
The attribute can either be present with any or no value, which means true,
or the attribute can be absent, which means false.
In templates, this can be programmed conveniently by boolean attributes.
If the resulting value is true , the attribute is rendered.
If it is false , the attribute is not rendered.
|
A document can contain input elements by which the user can enter data.
When the user enters data into one of these elements, the value is sent to the server and inserted into javascript variables of the interrupted javascript program.
All input elements can assign values to javascript left-hand-side expressions,
abbreviated lhs.
A left-hand-side expression can appear on the left of an assignment statement:
lhs = expression
.
These are some lhs:
x
--a javascript variable
obj[prop]
--a property in an object
arr[17]
--an element in an array
session["first-name"]
--a session property
session.name
--a session property
user["first-name"]
--a user property
user.name
--a user property
boolean input
Accept terms? |
Initial appearance: checked if lhs is When the user checks or unchecks the checkbox, the lhs will the set to true or false. |
text input
|
Initial appearance: with value of lhs.
If lhs does not exist, it will be initialised with the
When the user edits the text in the input, lhs will the set to the new value as soon as the focus leaves the input element. |
password input
|
Initial appearance: with value of lhs.
If lhs does not exist, it will be initialised with the
When the user edits the text in the input, lhs will the set to the new value as soon as the focus leaves the input element. |
textarea
|
Initial appearance: with value of lhs. If lhs does not exist, it will be initialised with the text content of the textarea element. When the user edits the text in the textarea, lhs will the set to the new value as soon as the focus leaves the textarea element. |
select
|
When the select element is rendered, the lhs determines which
option should be rendered as selected.
If lhs does not exist, it is initialised with the value of the
(first) option with When the user selects a different option, the name is assigned the value of that option. |
radio group
|
When the user selects a different radio button, the name is assigned the
value of that radio button.
The lhs determines which (if any) radio button should be rendered as selected.
If lhs does not exist, it is initialised with the value of the
(first) input with When the user selects a different radio button, the name is assigned the value of that option. |