JavaScript Application Framework

root

Icecube

Icecube is a JavaScript framework for quickly creating web applications with minimal effort:

<!DOCTYPE html>
<html>
  <head>
    <script src="javascripts/jquery-1.11.1.min.js"></script>
    <script src="javascripts/handlebars-v2.0.0.js"></script>
    <script src="javascripts/icecube.js"></script>
  </head>
  <body>
    <script type="text/x-handlebars-template">
      Hello World!
    </script>

    <script type="text/javascript">
      window.App = new Icecube.Application(function() {
        this.route("application")
      })
    </script>
  </body>
</html>

Get the latest version:

darcs get http://hub.darcs.net/stefan/icecube

Dependencies:

Routes

In Icecube, routes are defined to bind application states to URL patterns. The application route marks the application starting point.

window.App = new Icecube.Application(function() {
  this.route("application", {
    /* some route definition */
  })
})

Routes may include named parameters, which get passed to the templates ActionsHandler for further evaluation.

this.route("/hello/:name", {
  /* matches "#/hello/jason" and "#/hello/cassandra" */
  template: "say-hello"
})

You can pass an onShow callback to a route, which gets triggered, after the corresponding template has been rendered.

this.route("application", {
  onShow: function() {
    /* some callback */
  }
})

Templates

Icecube uses the handlebars templating engine, a powerful JavaScript library for building dynamic templates. If you are new to handlebars, read the documentation first.

Important: Templates get their name from the id attribute. The template id must be small caps and hypen case. E.g. post-comments but not postComments or post_comments. If the id attribute is missing, the template will internally be named application.

Icecube extends handlebars with the following helpers:

Translation helper

You can place translated text on templates using the {{t}} helper.

<ul class="crudButtons">
  <li>{{t "show"}}</li>
  <li>{{t "edit"}}</li>
  <li>{{t "delete"}}</li>
</ul>

See the I18n section for details on internationalising your application.

Actions

You can use the {{action}} helper to make an HTML element clickable. When a user clicks the element, an action will be triggered in the corresponding ActionUnit:

<div id="toggle">
  <!-- some html -->
</div>

{{#if isVisible}}
  <button {{action "hide"}}>Hide</button>
{{else}}
  <button {{action "show"}}>Show</button>
{{/if}}

Actions are not limited to click events. With the on option you can specify the type of event, that will trigger the action:

<input type="text" {{action "save" on="enter" }} />

Map

You can map a template snippet to a json object using the {{#map}} helper. The given block will be applied to each key-value pair. Each pair can be addressed using the key and value variables.

<div>
  <ul>
    {{#map errors}}
      <li>{{key}}: {{value}}</li>
    {{/map}}
  </ul>
</div>

Pagination

Icecube has it´s built-in pagination. To place a pagination bar on a template, use the paginate helper.

{{#each posts}}
  <div>
    <h3>{{title}}</h3>
    {{body}}
    <div class="tags">{{tags}}</div>
  </div>
{{/each}}

{{paginate posts}}

See the Pagination section for detailed information.

Action units

In Icecube, every template has an associated action unit. Action units allow you to apply display logic to your templates. If an user performs an event like clicking a button, the corresponding action will be triggered in the action unit:

<script type="text/x-handlebars-template" id="name">
  <label>Please enter your name:</label>
  <input type="text" id="my-name" />
  <button {{action "sayHello"}}>greet</button>
</script>

<script type="text/javascript">
  window.App = new Icecube.Application(function() {
    this.route("application", {
      template: "name"
    })
  })

  window.NameActions = new Icecube.ActionUnit({
    sayHello: function() {
      var name = $("#my-name").val()
      alert("Hello " + name)
    }
  })
</script>

The action initialize gets triggered, after the corresponding template has been activated. It´s params argument contains all url parameters defined with the calling route.

window.FormActions = new Icecube.ActionUnit({
  initialize: function(params) {
    alert("Let´s start!")
  }
})

The table below shows how action unit names map to template names:

Action Unit Name Template Name
PhotoActions photo
AdminUserProfileActions admin-user-profile

Stores

A Store is an object containing methods for reading, updating and removing data, that the application presents to the user. Any logic that handles data i/o should be provided by stores.

window.DraftStore = new Icecube.Store({
  save: function(params) {
    localStorage.setItem("draft", params)
  },

  load: function() {
    return localStorage.getItem("draft")
  }
})

DraftStore.save("Some draft")
DraftStore.load() /*=> "Some draft" */

I18n

Icecube allows you to store text blocks for multiple languages and switch the active language at runtime. Use locales to internationalise your application:

I18n.locale("en", {
  key: "Translation"
})

To set the current language, use the attribute I18n.language:

I18n.language = "pl" /* set language to polish */

Use the {{t}} helper to place internationalised text into a template:

<div>
  {{t "someText"}}
</div>

This examples shows a form with two buttons to switch the language at runtime:

<script type="text/x-handlebars-template" id="post">
  <label>{{t "title"}}: </label><br/><input /><br/>
  <label>{{t "body"}}: </label><br/><textarea></textarea><br/>
  <label>{{t "tags"}}: </label><br/><input /><br/>
  <label>{{t "author"}}: </label><br/><input />

  <p>
    <button {{action "langEn"}}>EN</button>
    <button {{action "langDe"}}>DE</button>
  </p>
</script>

<script type="text/javascript">
  window.App = new Icecube.Application(function() {
    this.route("application", {
      template: "post"
    })
  })

  I18n.locale("en", {
    title: "Title",
    body: "Body",
    tags: "Tags",
    author: "Author"
  })
  I18n.locale("de", {
    title: "Titel",
    body: "Text",
    tags: "Tags",
    author: "Autor"
  })

  window.PostActions = new Icecube.ActionUnit({
    langEn: function() {
      I18n.language = "en"
    },
    langDe: function() {
      I18n.language = "de"
    }
  })
</script>

Pagination

Icecube comes with built-in pagination. You can use every array as data source for pagination. To make an array ready for pagination, use the paginate method:

var paginatedArray = someArray.paginate({page: 1})

Per default pagination will load ten entries per page. To change this value use the perPage attribute:

paginatedArray.perPage = 5

You can place pagination buttons on your template by using the {{paginate}} helper:

{{paginate paginatedArray}}