Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

487 lines (367 sloc) 10.838 kb

Synopsis

Transparency is a client-side template engine which binds data to DOM. Just call .render(data).

<div id="template">
  <span class="greeting"></span>
  <span class="name"></span>
</div>
var hello = {
  greeting: 'Hello',
  name:     'world!'
};

$('#template').render(hello);
<div id="template">
  <span class="greeting">Hello</span>
  <span class="name">world!</span>
</div>

Build Status

Features

  • Data binding by convention - No extra markup in the views
  • Collection rendering - No loops and partials
  • Nested objects and collections - No configuration, just conventions
  • Directives - No DSL, just functions
  • Cached templates by default - No separate lookup/compile/use steps
  • Fast - In most real-world cases, it's faster than any other template engine or hand-crafted bindings (*)
  • Compatible - Tested on IE6+, Chrome and Firefox

(*) Take with a grain of salt, as "real-world performance" isn't that easy to define or measure. Anyway, jsperf.com should give an idea: http://jsperf.com/transparency-vs-handlebars-finite-list/3 http://jsperf.com/transparency-vs-handlebars-infinite-list/3 http://jsperf.com/dom-vs-innerhtml-based-templating/366

If interested, see other performance tests at browser folder. See also Frequently asked questions.

Try it

Demo website with interactive examples.

Use it

Get the compiled and minified version and include it to your application. jQuery is optional, but if you happen to use it, Transparency registers itself as a plugin.

<script src="js/jquery-1.7.1.min.js"></script>
<script src="js/transparency.min.js"></script>

Node users can also install via NPM:

npm install transparency

For server-side use, see spec folder and the awesome jsdom for the details.

Examples

Binding values

Transparency binds JavaScript objects to DOM a element by id, class,name attribute and data-bind attribute. Values are escaped before rendering.

Template:

<div id="container">
  <div id="hello"></div>
  <div class="goodbye"></div>
  <input type="text" name="greeting" />
  <button class="hi-button" data-bind="hi-label"></button>
</div>

Javascript:

var hello = {
  hello:      'Hello',
  goodbye:    '<i>Goodbye!</i>',
  greeting:   'Howdy!',
  'hi-label': 'Terve!' // Finnish i18n
};

// with jQuery
$('#container').render(hello);

// ..or without
Transparency.render(document.getElementById('container'), hello);

Result:

<div class="container">
  <div id="hello">Hello</div>
  <div class="goodbye">lt;i&gt;Goodbye!&lt;/i&gt;</div>
  <input type="text" name="greeting" value="Howdy!" />
  <button class="hi-button" data-bind="hi-label">Terve!</button>
</div>

Rendering a list of models

Template:

<ul id="activities">
  <li class="activity"></li>
</ul>

Javascript:

var activities = [
  {activity: 'Jogging'},
  {activity: 'Gym'},
  {activity: 'Sky Diving'},
];

$('#activities').render(activities);

// or
Transparency.render(document.getElementById('activities'), activities);

Result:

<ul id="activities">
  <li class="activity">Jogging</li>
  <li class="activity">Gym</li>
  <li class="activity">Sky Diving</li>
</ul>

Rendering a list of plain values

With plain values, Transparency can't guess how you would like to bind the data to DOM, so a bit of help is needed. Directives are just for that.

Access to the plain values within the directives is provided through this.value. There's a whole lot more to say about the directives, but that's all we need for now. For the details, see section Directives.

Template:

<div>
  <div class="comments">
    <label>Comments:</label><span class="comment"></span>
  </div>
</div>

Javascript:

var comments, directives;

comments = ["That rules", "Great post!"];

// See section 'Directives' for the details
directives = {
  comment: {
    text: function() {
      return this.value;
    }
  }
};

$('.comments').render(comments, directives);

Result:

<div>
  <div class="comments">
    <label>Comments</label><span class="comment">That rules</span>
    <label>Comments</label><span class="comment">Great post!</span>
  </div>
</div>

Nested lists

Template:

<div class="container">
  <h1 class="title"></h1>
  <p class="post"></p>
  <div class="comments">
    <div class="comment">
      <span class="name"></span>
      <span class="text"></span>
    </div>
  </div>
</div>

Javascript:

var post = {
  title:    'Hello World',
  post:     'Hi there it is me',
  comments: [ {
      name: 'John',
      text: 'That rules'
    }, {
      name: 'Arnold',
      text: 'Great post!'
    }
  ]
};

$('.container').render(post);

Result:

<div class="container">
  <h1 class="title">Hello World</h1>
  <p class="post">Hi there it is me</p>
  <div class="comments">
    <div class="comment">
      <span class="name">John</span>
      <span class="text">That rules</span>
    </div>
    <div class="comment">
      <span class="name">Arnold</span>
      <span class="text">Great post!</span>
    </div>
  </div>
</div>

Nested objects

Template:

<div class="person">
  <div class="firstname"></div>
  <div class="lastname"></div>
  <div class="address">
    <div class="street"></div>
    <div class="zip"><span class="city"></span></div>
  </div>
</div>

Javascript:

var person = {
  firstname: 'John',
  lastname:  'Wayne',
  address: {
    street: '4th Street',
    city:   'San Francisco',
    zip:    '94199'
  }
};

$('.person').render(person);

Result:

<div class="container">
  <div class="firstname">John</div>
  <div class="lastname">Wayne</div>
  <div class="address">
    <div class="street">4th Street</div>
    <div class="zip">94199<span class="city">San Francisco</span></div>
  </div>
</div>

Directives

Directives are actions Transparency performs while rendering the templates. They can be used for setting element text or html content and attribute values, e.g., class, src or href.

Directives are plain javascript functions defined in a two-dimensional object literal, i.e.,

directives[element][attribute] = function(params) {...}

where element is value of id, class, name attribute or data-bind attribute of the target element. Similarly, attribute is the name of the target attribute.

Directive functions receive current model as this paramater. In addition, they receive current element as params.element, current index as params.index and current value as params.value.

The return value of a directive function is assigned to the matching element's attribute. The return value should be string.

Template:

<div class="person">
  <span class="name"></span>
  <a class="email"></a>
</div>

Javascript:

var person, directives;

person = {
  firstname: 'Jasmine',
  lastname:  'Taylor',
  email:     'jasmine.tailor@example.com'
};

directives = {
  name: {
    html: function(params) {
      return "<b>" + this.firstname + " " + this.lastname + "</b>";
    }
  },

  email: {
    href: function(params) {
      return this.email;
    }
  }
};

$('.person').render(person, directives);

Result:

<div class="person">
  <span class="name"><b>Jasmine Taylor</b></span>
  <a class="email" href="mailto:jasmine.tailor@example.com">jasmine.tailor@example.com</a>
</div>

Nested directives

Template:

<div class="person">
  <span class="name"></span>
  <span class="email"></span>
  <div class="friends">
    <div class="friend">
      <span class="name"></span>
      <span class="email"></span>
    </div>
  </div>
</div>

Javascript:

person = {
  firstname:  'Jasmine',
  lastname:   'Taylor',
  email:      'jasmine.taylor@example.com',
  friends:    [ {
      firstname: 'John',
      lastname:  'Mayer',
      email:     'john.mayer@example.com'
    }, {
      firstname: 'Damien',
      lastname:  'Rice',
      email:     'damien.rice@example.com'
    }
  ]
};

nameDecorator = function() { "<b>" + this.firstname + " " + this.lastname + "</b>"; };

directives = {
  name: { html: nameDecorator },

  friends: {
    name: { html: nameDecorator }
  }
};

$('.person').render(person, directives);

Result:

<div class="person">
  <span class="name"><b>Jasmine Taylor</b></span>
  <span class="email">jasmine.taylor@example.com</span>
  <div class="friends">
    <div class="friend">
      <span class="name"><b>John Mayer</b></span>
      <span class="email">john.mayer@example.com</span>
    </div>
    <div class="friend">
      <span class="name"><b>Damien Rice</b></span>
      <span class="email">damien.rice@example.com</span>
    </div>
  </div>
</div>

Debugging templates, data and Transparency

http://leonidas.github.com/transparency/ is great place to fiddle around with your data and templates.

To enable debug mode, call .render with a {debug: true} config and open the javascript console.

$('container').render(data, {}, {debug: true});

Getting help

Development environment

You need node.js 0.6.x and npm.

Install dependencies:

npm install
npm install -g uglify-js
npm install -g coffee-script

Run tests

npm test

Run tests during development for more verbose assertion output

node_modules/jasmine-node/bin/jasmine-node --coffee --verbose spec

Generate Javascript libs

cake build

Use debugger statement to debug spec scripts.

Contributing

All the following are appreciated, in an asceding order of preference

  1. A feature request or a bug report
  2. Pull request with a failing unit test
  3. Pull request with unit tests and corresponding implementation

In case the contribution is going to change Transparency API, please create a ticket first in order to discuss and agree on design.

There's an article regarding the original design and implementation. It might be worth reading as an introduction.

Jump to Line
Something went wrong with that request. Please try again.