Section Outline

XHTML Markup

Unlike a Web browser, the JavaScript Server Pages compiler requires the use of proper XML markup because it internally relies on existing XML processing technologies. Any XML serialization of HTML is supported, including, but not limited to:

The validity of XHTML markup may be optionally verified using the XML schemas provided with this distribution. However, while the use of invalid XHTML, such as obsolete or non-existant tags and attributes, will be tolerated, it is mandatory that the mark-up be well-formed, since unparseable XML content will cause a compile-time error.

Markup Examples

Invalid Mark-Up - Not Well-Formed

...
<p class=main>
Lorem ipsum dolor <br>
new line <br>
2 <= x + 5
<div class="remarks"> This is a <ul> tag. Let's rock&roll!</div>
...

Valid Mark-Up

...
<p class="main">
Lorem ipsum dolor <br />
new line <br />
2 &lt;= x + 5
</p>
<div class="remarks"> This is a &lt;ul&gt; tag. Let's rock&amp;roll!</div>
...

Scope of Restrictions

Although it is strongly recommended to use well-formed mark-up throughout your Web site, the well-formedness requirement applies only to JavaScript Client Pages, i.e. to any dynamic HTML code that will be rendered using the JSCP framework.

This implies that if your current Web site is written in HTML 4.x, or even unstructured "tag soup" that does not have a DTD or schema attached to it, you can still develop new content in JSCP without rewriting your existing code.

Embedded JavaScript Code

JavaScript code can be embedded into a page using a <?js ... ?> processing instruction, which is very similar to the way code is included into pages in PHP.

Given below are a few examples of how embedded code can be used

Iteration

<ul>
<?js for (var i=1;i<10;i++) { ?>
<li>
<?js text('Item #' + i); ?>
</li>
<? } ?>
</ul>

Logic

<ul>
<?js for (var i=1;i<10;i++) { ?>
<li>
<?js
if (i %% 2) {
attribute('class', 'even');
} else{
attribute('class', 'odd');
}
?>
<?js text('Item #' + i); ?>
</li>
<? } ?>
</ul>

Embedded Code Gotchas

Unlike PHP, which outputs plain text to a stream, JavaScript Client Pages output proper DOM-generating code that has to construct a proper tree of elements, and the compiler relies on the input being well-formed XML.

Therefore, the following would be possible in PHP but not in JSCP:

<?php if ($type = 1): ?>
</li>
<?php else: ?>
</li>
<li class="type-2">
Type 2
</li>
<?php endif; ?>

Fortunately, in most cases, such code can be easily refactored to meet JSCP's XML well-formedness requirement.

Interfacing with Invoking Code

In order to pass content or parameters to a page, a "parameters" object may be passed by the invoking code:

JSClientPage.render(
'page',
'target',
{
firstName: 'John',
lastName: 'Doe',
hobbies:
[
'rock',
'hiking',
'canoeing'
]
}
);

These parameters become accessible in the JavaScript Client Page via the input object. For instance, the firstName parameter would become input.first-name.

XML-based Markup

While embedded code is very easy to use in simple pages, in more complex scenarios, it may become rather unwieldy, especially given that as of now, there is no direct IDE support for JavaScript code embedded via processing instructions (e.g. code folding).

It is also important to note that the compiler does not understand JavaScript; nor does it detect JavaScript parse errors at compile time.

In order to address common scenarios requiring the use of control structures in templates, as well as outputting data, a number of extension elements have been provided in the JSClientPages namespace. These elements provide a cleaner way of representing

Outputting Data

Element Name js:output
Description Outputs the value of a JavaScript expression.

The semantics of this expression are similar to <?js text(...) ?>.

Important: Character strings without quotes are interpreted as identifiers rather than literal text. The use of undefined identifiers in JavaScript expressions will result in a runtime error.
Attributes
Attribute Name Description Required Example
value The JavaScript expression to output Yes input.firstName + ' ' + input.lastName
Occurs In
  • HTML block elements
    • div
    • p
    • h1, h2, h3, h4, h5, h6
    • etc.
  • HTML inline elements
    • span
    • textarea
    • button
    • etc.
Example
<table class="details">
<tbody>
<tr>
<th>First Name:</th>
<td> <js:output value="input.person.firstName" /> </td>
</tr>
<tr>
<th>Last Name:</th>
<td> <js:output value="input.person.lastName" /> </td>
</tr>
</tbody>

</table>

Conditions

js:condition

Description

Represents a condition construct, similar to if..else and if...then...else construct in programming languages.

This element can only be used to represent a single condition. Switches with multiple conditions will be discussed in the next section.

Synopsis

<js:condition>
<js:if> <!-- a JavaScript condition --> </js:if>
<js:then> ;<!-- mark-up and/or code </js:then>
<js:else> <!-- mark-up and/or code --> ;</js:else> <!-- optional -->
</js:condition>

Child Elements

js:if required
Description

The JavaScript condition to be evaluated. The condition will be evaluated as if it were included directly in a JavaScript statement with 0s, null values, undefined values and empty strings or arrays being equivalent to false and everything else evaluating to true.

Content

JavaScript code. Any characters or combinations of characters that have a special meaning in XML should be replaced with entities. Notable examples include "<", ">" and &.

Example
<js:if>
input.employee.position == 'manager'
</js:if>
js:then required
Description

The block that will be evaluated and displayed if the condition is true. This block may contain any combination of mark-up, embedded code and other tags.

Contents

js:then may contain any of the following:

  • XHTML mark-up
  • Other elements from the js namespace, including conditions.
  • JavaScript code in the <js ... ?> processing instruction.
Example
<js:condition>
<js:if> input.employee.position == 'manager' </js:if>
<js:then>
<js:forEach items="input.employee.subordinates" item="subordinate">
<js:output value="subordinate.firstName + ' ' + subordinate.lastName" />
</js:forEach>
</js:then>
</js:condition>
js:else optional
Description

The block that will be evaluated and displayed if the condition is false. Like js:then, js:else can contain code and markup.

Content
  • XHTML markup
  • Other elements in the js namespace, including other conditions.
  • Embedded code in the <?js ... ?> processing instruction
Example
<js:condition>
<js:if> input.employee.position == 'manager' </js:if>
<js:then>
A manager with <js:output value="input.employee.subordinates.count" />
</js:then>
<js:else>
<span class="non-manager"> Not a manager </span>
</js:else>
<js:condition>

Switches

In JSCP, a switch is a series of conditions with attached code blocks where only one is expected to evaluate to true. Even in cases when two or more of the switch conditions are true, the first one takes precedence over the others.

In the most common case, switches check the value of a single variable against several possibilitiies in order to decide on a course of action. Given below is an example of this type of switch in JavaScript.

JavaScript Example:

switch (grade) {
case 'A':
evaluation = 'excellent';
break;
case 'B':
evaluation = 'good';
break ;
case 'C':
evaluation = 'fair';
break;
default:
evaluation = 'poor';
break;
}

In JSCP, a similar switch can be implemented as follows:

JavaScript Client Pages Example

<js:switch value="input.grade">
<js:case if="'A'">
<span class="grade-good">Excellent</span>
</js:case>
<js:case if="'B'">
<span class="grade-good">Good</span>
</js:case>
<js:case if="'C'">
<span class="grade-bad">Fair</span>
</js:case>
<js:default>
<span class="grade-bad">Poor</span>
</js:default>
</js:switch>

Loops over Collections

js:forEach

Description

Renders the same section of markup for every element of the specified JavaScript collection, which may be an array or an iterable object. The iteration will be implemented as a one of the following constructs depending on the type of object:

for (i=0;i< array.length;i++) {
render(array[i]);
}
for (var key in object) {
render(object[key]);
}

Synopsis

<js:forEach collection="items" item="item" key="itemKey">
<!--
Code and markup to output each item by referencing the "item" variable, possibly using the "itemKey" variable to indicate the number of the item within the collection in the case of an array or the name of the property in the case of an object.
-->
</forEach>

Attributes

items required
Description

A reference to a JavaScript collection, i.e. an array or an enumerable object, over which this section will be iterating

Examples
[
  • 'Windows',
  • 'Mac OS X',
  • 'Linux',
  • 'QNX'
]
{
  • code : 'ECMA-262',
  • name : 'ECMAScript',
  • implementations : [
    • 'JavaScript',
    • 'JScript.NET',
    • 'ActionScript',
    ]
}
item required
Description

The name of the iteration in which individual elements from the collection will be placed on every iteration. For instance, if the collection is named persons, it might be advisable to call the item person.

Example
<ul>
<js:forEach items="persons" item="person">
<li>
<js:output value="person.firstName + ' ' + person.lastName" />
</li>
</js:forEach>
</ul>
key optional

The name of the variable used to store one of the following:

The Item Index
If the items collection is an array, the key will represent the index of the number within the array, i.e. the number that can be used to locate the value using the [] operator.
The Property Name
If the items collection is an object, the key will contain the name of the properties returned by the for .. in construct.

Content

The <js:forEach> element can contain any of the following: