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}}