Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

<?xml version="1.0" encoding="utf-8"?>
<html>
<div style="float:right; margin: 0 0 10px 10px;">Version|opensocial-0.9

</div>

Overview

OpenSocial Templates gives you an easy, fast, and secure way to build
gadgets without using JavaScript to generate HTML. Use it to declaratively
create templates for your gadgets by making minor modifications to
standard HTML markup without using string concatenation and DOM
manipulation. Because the library is part of OpenSocial, you can use it
to bind to both the OpenSocial APIs and to custom variables that you define.

Hello World Gadget Example

Here is an example of a simple gadget that uses server-side OpenSocial Templates to display the text "Hello world!" in the gadget UI:

<source lang="xml">
<?xml version="1.0" encoding="UTF-8" ?>
<Module>

<ModulePrefs title="Hello World">
<Require feature="opensocial-templates">
</Require>
</ModulePrefs>
<Content type="html">
<![CDATA[

<script type="text/os-template">
<div style="font-size: 20px">Hello world!</div>
</script>
]]>
</Content>

</Module>
</source>

Setup

To use server-side OpenSocial Templates in your gadget, include the following tag in your

ModulePrefs

:

<source lang="xml">
<Require feature="opensocial-templates">
</Require>
</source>

Creating Templates

The canonical template format is well-formed XML that contains HTML and OpenSocial Template markup. To define a template inside of your gadget file, use

<script>

tags of

type="text/os-template"

, following this syntax:

<source lang="xml">
<script type="text/os-template">

</script>
</source>

Template markup can contain both HTML and custom tags.

Data Pipelining

OpenSocial Templates become a lot more useful when you can bind data to them. The OpenSocial Data Pipelining spec describes a declarative syntax for defining data to process in your gadget. You can access data from an external server or an OpenSocial container.

To work with data in your template, first add

<Require feature="opensocial-data" />

to your gadget's

ModulePrefs

. Then refer to the Data Pipelining spec and the examples below for the types of data that you can access.

Fetching data from OpenSocial

One tag you can use from the Data Pipelining spec is

<os:PeopleRequest>

, which returns profile information for a group or list of people. For example, if you want to access the current viewer's friend list, use the following code:

<source lang="xml">
<script xmlns:os="http://ns.opensocial.org/2008/markup" type="text/os-data">

<os:PeopleRequest key="friends" userId="@viewer" groupId="@friends"/>

</script>
</source>

Note that this example uses

<os:PeopleRequest>

with the following attributes:

  • key="friends"
    : this key gives you access to the data object from within the template
  • userId="@viewer"
    : sets the user to the current viewer
  • groupId="@friends"
    : sets the group to the user's friend list

You can find a complete list of fields to use with

<os:PeopleRequest>

in the Data Pipelining spec.

After you fetch the data, you can render it using the following OpenSocial Template:

<source lang="xml">

<script type="text/os-template">
<ul>
<li repeat="${friends}">
<span id="id${Context.Index}">${Cur.name.givenName}</span>
</li>
</ul>

</script>
</source>

Note that the template uses standard HTML list tags to format the friends list and sets the

id

attribute of each

span

node. It also uses the special

repeat

attribute to iterate over the friends object, the special variable

Cur

to reference the current item, and the

$\{\}

notation to de-reference data objects. You can find more detail about repeaters, special variables, and expressions in subsequent sections of this Developer Guide.

Here is the complete gadget that fetches the OpenSocial data and then renders it:

<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<Module>

<ModulePrefs title="Server-side Template">
<Require feature="opensocial-data" />
<Require feature="opensocial-templates">
</Require>
</ModulePrefs>
<Content type="html">
<![CDATA[
<script xmlns:os="http://ns.opensocial.org/2008/markup" type="text/os-data">
<os:PeopleRequest key="friends" userId="@viewer" groupId="@friends"/>
</script>

<script type="text/os-template">
<ul>
<li repeat="${friends}">
<span id="id${Context.Index}">${Cur.name.givenName}</span>
</li>
</ul>
</script>
]]>
</Content>

</Module>
</source>

See the Data Pipelining spec for more information about requesting other types of OpenSocial data, including viewer or owner profiles, activities, and container-specific endpoints.

Fetching data from a URL

In addition to fetching OpenSocial data to render into templates, you can also request JSON or text data from a URL using

<os:HttpRequest>

. Suppose you have the following

friends

JSON data object stored at

<nowiki>http://myfriendsserver.com</nowiki>

:

<source lang="javascript">
{

"friends" : [
{
"name": "David",
"interests": "Cooking"
},
{
"name": "Charles",
"interests": "Hiking"
},
{
"name": "Mary",
"interests": "Football"
}
]

}
</source>

You can fetch this data like this:

<source lang="xml">
<script xmlns:os="http://ns.opensocial.org/2008/markup" type="text/os-data">

<os:HttpRequest key="request" href="http://myfriendsserver.com"/>

</script>
</source>

Note that this example uses the

<os:HttpRequest>

tag with the following attributes:

  • key="request"
    : this key gives you access to the data object from within the template
  • href="http://myfriendsserver.com"
    : the URL where the data is stored

You can find the complete list of fields to use with the

<os:HttpRequest>

tag in the Data Pipelining spec.

After you fetch the data, you bind it to the template by setting the

require

attribute of the template's

script

tag to the data's

key

. Here is an example of a simple template that displays each friend's name and interests:

<source lang="xml">

<script type="text/os-template" require="request">
<ul>
<li repeat="${request.result.content.friends}">
<span>Name: ${Cur.name} Hobby: ${Cur.interests}</span>
</li>
</ul>

</script>
</source>

Here is the complete gadget that fetches the JSON data and then renders it:

<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<Module>

<ModulePrefs title="Server-side Template">
<Require feature="opensocial-data" />
<Require feature="opensocial-templates">
</Require>
</ModulePrefs>
<Content type="html">
<![CDATA[
<script xmlns:os="http://ns.opensocial.org/2008/markup" type="text/os-data">
<os:HttpRequest key="request" href="http://myfriendsserver.com"/>
</script>

<script type="text/os-template" require="request">
<ul>
<li repeat="${request.result.content.friends}">
<span>Name: ${Cur.name} Hobby: ${Cur.interests}</span>
</li>
</ul>
</script>
]]>
</Content>

</Module>
</source>

Expressions

Use template expressions to access your data. Embed expressions into the template XML using the syntax

$\{Expr\}

. Here is an example of template content that uses an expression to evaluate and display a viewer's name:

<source lang="xml">
<div>Hello ${Viewer.displayName}</div>
</source>

The syntax of template expressions is defined from a subset of the JSP Expression Language specification. You can use raw variable references in your expressions, as in the example above, or create more complex expressions that use operators, as in this example:

<source lang="xml">
<div>Next step is ${Step + 1}</div>
</source>

JSP Expression Language allows you to use most standard operators (e.g. comparison, arithmetic, etc.) in expressions, although OpenSocial Templates provides a few XML-escaped operators for use in XML. For example, you should use

$\{a lt b\}

instead of

$\{a < b\}

,

$\{a gt b\}

instead of

$\{a > b\}

, and

$\{a and b\}

instead of

$\{a && b\}

. See the full list of XML-escaped conditional operators in Conditional Operators.

Most expressions are evaluated as strings. The only exception is if the expression is enclosed in an attribute without additional text content, in which case OpenSocial Templates processes and evaluates the object that is referenced in the expression. In the following example, the Viewer object is passed in to the

os:Name

template.

<source lang="xml">
<os:Name person="${Viewer}"/>
</source>

By default OpenSocial Templates escapes all strings before inserting them into the HTML document. However, OpenSocial Templates may alternatively URL-encode or JavaScript-escape strings, depending on the context.

Conditional Operators

Below is a list of XML-escaped expressions and the conditional operators that they map to. You should use the XML-escaped versions of these operators to evaluate

if

expressions:

<table>

<tr>
<th>Conditional operator</th>
<th>XML-escaped expression</th>
</tr>

<tr>
<td>

&lt;

</td>
<td>

lt

</td>

</tr>

<tr>
<td>

&gt;

</td>
<td>

gt

</td>
</tr>

<tr>
<td>

&lt;=

</td>

<td>

lte

</td>
</tr>

<tr>
<td>

&gt;=

</td>
<td>

gte

</td>
</tr>

<tr>
<td>

&&

</td>
<td>

and

</td>
</tr>

<tr>
<td>

==

</td>

<td>

eq

</td>
</tr>

<tr>
<td>

!=

</td>
<td>

neq

</td>
</tr>

<tr>
<td>

||

</td>
<td>

or

</td>
</tr>

<tr>
<td>

!

</td>
<td>

not

</td>

</tr>
</table>

Variables

Templates have two types of variables: a set of global objects that are referenced by special variables and a set that includes all other declared JavaScript variables, including JSON data that's passed in to a template for processing and rendering.

Variables are accessed using the syntax

Object.Property

. For example, the notation

Foo.Bar

maps to getting the property

Bar

on the JSON object

Foo

. You can use this notation for arbitrarily deep nested properties, for example

Foo.Bar.Baz

maps to the property

Baz

on the JSON object

Foo.Bar

.

Equivalent JSON Notation

If Top and Viewer are JSON objects, then

$\{Top.Viewer.Name\}

evaluates to

data['Viewer']['Name']

.

Special Variables

OpenSocial Templates reserves a small set of special variables for template processing:

Cur

,

Context

,

Top

, and

My

. It also reserves the special tag

<os:Html>

. See below for details of how to use each variable and tag.

Cur

Use

Cur

to refer to the item that is currently being processed within a repeater. The example below repeats over a user's friends list and prints out each user's name:

<source lang="xml">
<div repeat="${Top.ViewerFriends}">

<div><strong>${Cur.Name}</strong></div>

</div>
</source>

See more information about repeaters in Repeated Elements.

Context

OpenSocial Templates uses the

Context

variable as a holding area for additional variables that you might need when processing templates. You can use the following properties of

Context

:

  • $\{Context.UniqueId\}
    : A unique ID of the template being rendered. This value is useful for generating HTML IDs.
  • $\{Context.Index\}
    : The index of the current item in the list that is being processed via a repeater.
  • $\{Context.Count\}
    : The count of items in the list that is being processed via a repeater.

Here is an example of using the

Context

variable to keep track of items that are used in a repeater element:

<source lang="xml">
<div repeat="${Top.ViewerFriends}">

Showing friend ${Context.Index} of ${Context.Count}:
Your friend's name is ${Cur.Name}

</div>
</source>

Top

The variable

Top

refers to all of the data that's available by key.

My

Use

My

to reference data that is passed into a template via the tag that calls the template. If you use the expression

$\{My.foo\}

, OpenSocial Templates first looks for an attribute named

foo

in the tag that called the template. If it does not find the attribute, it then looks for an element named

foo

.

Msg

Use

Msg

to access localized messages in templates and evaluate expressions within the message body.

For example, suppose you had a message bundle that included the following localized message:

<source lang="xml">
<messagebundle>

<msg name="PLAY_SONG">Click here to play Love song #15</msg>

</messagebundle>
</source>

In your template, you can use this markup to directly access and evaluate the localized message:

<source lang="xml">
<a href="${song.url}">${Msg.PLAY_SONG}</a>
</source>

You can even also use the

$\{\}

expression syntax to include an expression in the message bundle. For example:

<source lang="xml">
<messagebundle>

<msg name="PLAY_SONG">Click here to play ${song.title}</msg>

</messagebundle>
</source>

In this example, the expression

$\{song.title\}

in the message body is evaluated at the time of template rendering. Note that you cannot use repeaters and conditionals in messages and variable markup is evaluated in the context in which the message is placed.

See Localizing OpenSocial applications for specific instructions on setting up your gadget for localization.

Tags

<os:Html>

Use the

<os:Html>

tag to include dynamic content that you want to be treated as HTML (and not escaped) in your template.

For example, if you had an expression

$\{Cur.someText\}

whose value was "<b>Bold</b>",

Then if you evaluated the expression:

<source lang="xml">

${Cur.someText}

</source>

The result would be: <b>Bold</b>

However, if you pass the expression to the

os:Html

tag using the

code

attribute, like this:

<source lang="xml">
<os:Html code="${Cur.someText}"/>
</source>

Then the result would be: Bold (the word "Bold" in bolded font).

Note: Be careful when using this tag! You must properly sanitize the HTML content that you pass in, or else you can introduce XSS attacks.

<os:If>

Use the

<os:If>

tag to conditionally display content based on the evaluation of an expression. Use this syntax for

<os:If>

:

<source lang="xml">
<os:If condition="${Expr}">

</os:If>
</source>

For example, the content between the

div

tag below is rendered only if the expression

$\{Top.YourScore == Top.HighScore\}

evaluates to

true

:

<source lang="xml">
<os:If condition="${Top.YourScore h1. Top.HighScore}">

<div>You have the high score of ${Top.YourScore}!</div>

</os:If>
</source>

<os:Repeat>

Use

<os:Repeat>

to render a tag multiple times based on the evaluation of an expression. Use this syntax for the

<os:Repeat>

tag

<source lang="xml">
<os:Repeat expression="${Expr}">

</os:Repeat>
</source>

For example, you can use the template below to display a list of friends' names:

<source lang="xml">
<os:Repeat expression="${Top.ViewerFriends}">

<div>
Your friend's name is ${Cur.Name}
</div>

</os:Repeat>
</source>

You can also use the

var

attribute to set a variable name of your choice for the repeater, for example:

<source lang="xml">
<os:Repeat expression="${Top.ViewerFriends}" var="Friend">

<div>
Your friend's name is ${Friend.Name}
</div>

</os:Repeat>
</source>

Custom Tags

In addition to using built-in OpenSocial Templates tags, you can also define custom tags to use in your gadget. You can create custom tags inline in your gadget, or refer to tags that are defined in an external template library.

Defining a Namespace

You must register all of your custom tags in a unique namespace. You cannot use the default (HTML) namespace.

Typically the best way to uniquely create a namespace is to use the URL of your domain. However, full URLs tend to be long and unwieldly to insert into tag names, so you can create a prefix instead. For example, if you want to register the namespace

example.com/myapp

, you can choose the prefix

myapp

and all of your custom tags will take the form

<myApp:TagName>

.

Inline Tags

You can create a custom tag out of any inline template by adding the

tag

attribute to the

<script>

tag and using

xmlns

to declare your namespace.

Use this syntax to create a custom inline tag:

<source lang="xml">
<script type="text/os-template" xmlns:yourNamespace="yourURL" tag="yourNamespace:tagName">

</script>
</source>

Note: You must declare your namespace in the

script

block for each custom inline tag you create.

Here is an example of creating a custom Hello World tag:

<source lang="xml">
<script type="text/os-template" xmlns:myapp="http://example.com/myapp" tag="myapp:HelloWorld">

<div style="font-size: 40px">Hello World</div>

</script>
</source>

Here is an example of using the tag that you just created:

<source lang="xml">
<script type="text/os-template">

<myapp:HelloWorld/>

</script>
</source>

You can pass parameters into custom tags as XML attributes or elements, and access the parameters using the special variable

$\{My\}

.

Here is an example of passing in a color parameter to the custom Hello World template:

<source lang="xml">
<script type="text/os-template" xmlns:myapp="http://example.com/myapp" tag="myapp:HelloWorld">

<div style="color: ${My.MessageStyle.color}">Your message is: ${My.message}</div>

</script>

<script type="text/os-template">

<myapp:HelloWorld message="Hello World">
<MessageStyle color="blue"/>
</myapp:HelloWorld>

</script>

</source>

External Tag Libraries

It is good practice to gather your template definitions into a single custom library, rather than defining them in all in the same file as your gadget.

Create your custom template library in a well-formed, valid XML file and fill in template definitions according to this structure:

<source lang="xml">
<Templates xmlns:foo="http://foo.com/">

<Namespace prefix="foo" url="http://foo.com/"/>

<Style>

.warning { color: red; }
</Style>

<JavaScript>

function usedByAllTemplates() { ... };
</JavaScript>

<Template tag="foo:bar">

</Template>

<TemplateDef tag="foo:baz">
<Template> </Template>
<Style> </Style>
<JavaScript>

function usedByFooBaz() { ... };
</JavaScript>
</TemplateDef>

</Templates>
</source>

<blockquote>Note: Use

<Template>

and

<TemplateDef>

tags to define templates in a library rather than

<script>

tags of

type="text/os-template"

.</blockquote>

<p>Refer to the table below for a list of tags to use when defining your template library:
</p>

<table border="1">
<tr>
<th>Tag</th>
<th>Usage</th>
</tr>
<tr>
<td>

&lt;Templates&gt;

</td>
<td>Declares all the namespaces used in this library to the XML parser. You must put this tag at the outer-most level of your XML file and list <b>all</b> the custom and pre-defined namespaces that you use in this library. Use the syntax

xmlns:<i>namespace_prefix</i>="<i>namespace_URL</i>"

for <strong>each</strong> namespace. For example, if you use any tags in the OpenSocial namespace via the OpenSocial Templates library, you must include

xmlns:os="http://www.opensocial.org/"

.
</td>
</tr>
<tr>
<td>

&lt;Namespace&gt;

</td>
<td>Declares your custom namespace. You should only create one namespace per library file. Set the values of your namespace's prefix and URL using the syntax

prefix="<i>namespace_prefix</i>" url="<i>namespace_URL</i>"

.
</td>
</tr>
<tr>
<td>

&lt;Style&gt;

</td>
<td>Defines style settings in CSS for your library (at the top-level of the XML file) or individual templates (within

&lt;TemplateDef/&gt;

tags). </td>
</tr>
<tr>
<td>

&lt;JavaScript&gt;

</td>
<td>Defines JavaScript functions for your library (at the top-level of the XML file) or individual templates (within

&lt;TemplateDef/&gt;

tags).</td>
</tr>
<tr>
<td>

&lt;Template&gt;

</td>
<td>Sets declarative markup for a template.</td>
</tr>
<tr>
<td>

&lt;TemplateDef&gt;

</td>
<td>Defines a more complex template, which can enclose its own local

&lt;Template/&gt;

,

&lt;Style/&gt;

, and

&lt;JavaScript/&gt;

tags.</td>
</tr>
</table>

For example:

<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<Templates xmlns:os="http://opensocial.org/templates">

<Namespace prefix="os" url="http://opensocial.org/templates">
<Style>
large-font: {
font-size: 20px;
}
</Style>
<Template tag="os:HelloWorld">
<div style="large-font">Hello World!</div>
</Template>
<TemplateDef tag="os:ShowPerson">
<Style>
profile-image: {
padding-right: 5px;
width: 32px;
height: 32px;
}
</Style>
<Template>
<img if="${My.person.ThumbnailUrl}" src="${My.person.ThumbnailUrl}"
class="profile-image"/>
<a href="${My.person.ProfileUrl}" target="_top">${My.person.Name}</a>
</Template>
</TemplateDef>

</Templates>
</source>

To load this template library into your gadget, add the

<Param name="requireLibrary">

tag to the

<Require feature="opensocial-templates">

tag in your gadget. The content of the

<Param>

tag must be a valid Template library XML file. If you use a relative URL path, it is interpreted in relation to the location of the Gadget Spec XML file.

For example:

<source lang="xml">
<Require feature="opensocial-templates">

<Param name="requireLibrary">http://www.example.com/templates.xml</Param>

</Require>
</source>

Use multiple

<Param>

tags to load multiple libraries. For example:

<source lang="xml">
<Require feature="opensocial-templates">

<Param name="requireLibrary">http://www.example.com/templates.xml</Param>
<Param name="requireLibrary">http://www.example.com/moretemplates.xml</Param>

</Require>
</source> Attributes h1. h2.

if

Set the

if

attribute of an element to an expression and OpenSocial Templates only displays the element if the expression evaluates to true. For example, the text between the

&lt;div&gt;

tags below is only displayed if

Top.YourScore == Top.HighScore

:

<source lang="xml">
<div if="${Top.YourScore Top.HighScore}">

You have the high score of ${Top.YourScore}!

</div>
</source>

You can set the

if

attribute for any element within a template, as in the examples below:

<source lang="xml">

<os:ShowPerson person="${Top.Owner}" if="${Top.HasOwner}"/>

<div repeat="${Top.ViewerFriends}" if="${Cur.profileUrl}">

Link to: <a href="${Cur.profileUrl}">${Name}</a>

</div>

</source>

repeat

You can set the

repeat

attribute of a tag to an expression and OpenSocial Templates renders the tag against each of the results. Use the special variable

Cur

to reference the current item being evaluated in the repeated list.

The following example iterates over all items of the array

Top.ViewerFriends

and displays each friend object's name:

<source lang="xml">
<div repeat="${Top.ViewerFriends}">

Your friend's name is ${Cur.Name}

</div>
</source>

You can also use nested repeats with the

Cur

keyword when iterating over multi-dimensional arrays of data. For example:

<source lang="xml">
<!--
table: [

]
-->
<script type="text/os-template">

<div repeat="${table}">
<div repeat="${Cur}">
Element: ${Cur}

</div>

</div>

</script>
</source>

index
,
var

As a convenience, you can rename the

Cur

variable and specify an index variable by adding

var

and

index

attributes, respectively:

<source lang="xml">

<div repeat="${Top.ViewerFriends}" var="${Friend}">

Your friend's name is ${Friend.Name}

</div>

<div repeat="${rows}" index="x">

<div repeat="${cols}" index="y">
<span> row="${x}" col="${y}"</span>
</div>

</div>
</source>

context

You can explicitly set the scope of data to evaluate using the

context

attribute. For example, to repeat over

Interests

of the first object in the data

Friends

, you can use this expression:

<source lang="xml">
<div context="${Friends0}">

<div repeat="${Interests}">
${Title}
</div>

</div>
</source>

require

Use the

require

attribute to specify all data that's required for rendering your inline template. The value of

require

should be a comma-separated list of top-level variable names for the required data. If you list more than one variable, the template only renders when all of the variables are set.

For example, the message below is only rendered when both

$Viewer

and

$Owner

are set (i.e. non-null):

<source lang="xml">
<script type="text/os-template" require="Viewer, Owner">

Hello, <os:Name person="${Viewer}"/>, welcome to <os:Name person="${Owner}"/>'s application

</script>
</source>

autoUpdate

Set the

autoUpdate

attribute to

true

in your template definition if you want the template to be re-rendered automatically when any of its required data changes.

For example, the content of the template below is automatically re-rendered whenever the

Friend

data is modified via the function

opensocial.data.DataContext.putDataSet("Friend", friend)

:

<source lang="xml">
<script type="text/os-template" require="Friend" autoUpdate="true">

You have selected, <os:Name person="${Friend}"/>.

</script>
<script type="text/javascript">

function setFriend(friend) {
opensocial.data.DataContext.putDataSet("Friend", friend);
}

</script>
</source>

</html>

  • No labels