A tiny templating plugin for JQuery with syntax inspired by Knockout
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
LICENSE
README.md
jquery.smack-min.js
jquery.smack.js
sample.html

README.md

Smack

Smack is a tiny (614 bytes minified) templating plugin for jQuery with a surprisingly powerful syntax inspired by Knockout. It achieves smallness mostly by deferring manipulation to jQuery so it's only small if you already have jQuery as a dependency of course.

Documentation

Smack binds values from a context object to the template by looking for data-bind attributes on elements. It can bind to an attribute or to the text content of the element, attributes are created if not defined in the template.

The following demonstrates loading a template and applying data bindings. Note that element here is modified and data bindings are applied.

<a data-bind="href: blogUrl">Home</a> 
<h1 data-bind="title"></h1>
<p>
  Published <abbr data-bind="friendlyDate,title:date"></abbr>
  <span data-bind="in {category}, "></span>
  <span data-bind="!'by <strong>{author}</strong>.'"></span>.
</p>
<ul>
  <li data-bind="#tags"><a data-bind=".,href:'?tag={.}'"></a></li>
</ul>
<p data-bind="?admin"><a href="#">Edit</a></p>
<p data-bind="?!admin"><a href="#">Report</a></p>
<div data-bind="!content"></div>
<h3 data-bind="'Comments ({comments.length})'"></h3>
<ul>
  <li data-bind="#comments">
    <strong data-bind="author"></strong>
    <p data-bind="text"></p>
    <p data-bind="?likes.length">Liked by <em data-bind="#likes,'{.} '"></em></p>
  </li>
</ul>
// Load template
var template = $("#template").html();

// Parse template to jQuery object
var element = $(template)

// Apply data-bindings
element.smack(context);

The examples below use the following context

{
  blogUrl: "http://www.example.com",
  author: {
    name: "Bob Bobson"
  },
  category: "Javascript"
  title: "Hello world", 
  date: "2014-01-01", 
  friendlyDate: "Yesterday",
  tags: ["tiny", "template", "jquery"], 
  content: "<p>This is a simple <strong>smack</strong> template.</p>",
  comments: [
    {author: "Bob", text: "Great stuff!", likes: ["Cecil","Mallory"]},
    {author: "Alice", text: "Indeed!"}
  ]
}

Simple binding to element content

Simple binding replaces content of the template element by the specified value, the value is first HTML escaped to prevent javascript injection attacks.

<h1 data-bind="title"></h1>

result:

<h1>Hello world</h1>

Values can be specified at any depth by separating members with . (fullstops).

<p data-bind="author.name"></p>

result:

<p>Bob Bobson</p>

Member specifications also support fallbacks with the | (bar) character.

<p data-bind="author.nick|name"></p>

result:

<p>Bob Bobson</p>

Raw HTML binding to element content

To bind raw HTML to element content, simply append ! to the context path specification as follows.

<div data-bind="!content"></div>

result:

<div><p>This is a simple <strong>smack</strong> template.</p></div>

Binding to element attributes

When binding to attributes, specify the attribute name before the context path specification separating the two with a : (colon) character.

<a data-bind="href: blogUrl">Home</a>

results:

<a href="http://example.com">Home</a>

Multiple bindings

Multiple bindings can be specifed for an element by separating then with , (comma).

<p>Published <abbr data-bind="friendlyDate,title:date"></abbr></p>

results:

<p>Published <abbr title="2014-01-01">Yesterday</abbr></p>

String interpolation

Both escaped and unescaped binding to element content, and attribute binding supports string interpolation by including a ' (apostrophe) quoted string and using {path} to insert values from context.

<p>
  <span data-bind="!'in <em>{category}</em>, '"></span>
  <span data-bind="'by {author.name}.'"></span>.
</p>

results:

<p>
  <span>in <em>javascript</em></span>
  <span>by Bob Bobson</span>.
</p>

Conditionals

Elements can be excluded or inluded depending on the truthyness of the value specified by a context specifier. Simply add a ? before the path specification to test the truthyness of a value.

Sometimes it is necessary to reverse the conditional in the template, to do this use ?! to include an element only if the value is falsy.

<p><a data-bind="?admin" href="#">Edit</a></p>
<p><a data-bind="?!admin" href="#">Report</a></p>

yields the following when admin is truthy,

<p><a href="#">Edit</a></p>

and the following when falsy.

<p><a href="#">Report</a></p>

Collection iteration

Anything that supports enumeration such as an Array or Object can be iterated over and bound to a sub-template.

<ul>
  <li data-bind="#tags"><a data-bind=".,href:'?tag={.}'"></a></li>
</ul>

results:

<ul>
  <li><a href="?tag=tiny'">tiny</a></li>
  <li><a href="?tag=template'">template</a></li>
  <li><a href="?tag=jquery'">jquery</a></li>
</ul>

Naturally iteration can be nested to an arbitrary depth.

<ul>
  <li data-bind="#comments">
    <strong data-bind="author"></strong>
    <p data-bind="text"></p>
    <p data-bind="?likes.length">Liked by <em data-bind="#likes,'{.} '"></em></p>
  </li>
</ul>

results:

<ul>
  <li>
    <strong>Bob</strong>
    <p>Great stuff!</p>
    <p>Liked by <em>Cecil </em><em>Mallory </em></p>
  </li>
  <li>
    <strong>Alice</strong>
    <p>Great indeed</p>
  </li>
</ul>