Basic Live Binding Example

EJS sets up live templating binding when a can-map's properties are read
via attr within a magic tag. To make this template
respond to changes in the teacher data, first rewrite the template
to use the attr method to read properties and list( observeList, cb(item, i) )
to iterate through a list like:

... but don't slap it too hard, you'll need it for building awesome apps.

Demo

The following demo shows an EJS template being rendered with observable data.
It demonstrates live binding to attributes. The template and all data properties
are editable, so experiment!

## Magic Tags

EJS uses 5 types of tags:

<%= CODE %> - Runs JS Code and writes the escaped result into the result of the template.

The following results in the user seeing "my favorite element is <blink>BLINK<blink>" and not
BLINK.

<div>my favorite element is <%= '<blink>BLINK</blink>' %>.</div>

<%== CODE %> - Runs JS Code and writes the unescaped result into the result of the template.

The following results in "my favorite element is B.". Using <%== is useful
for sub-templates.

<div>my favorite element is <%== '<B>B</B>' %>.</div>

<%% CODE %> - Writes <% CODE %> to the result of the template. This is very useful for generators.

<%%= 'hello world' %>

<%# CODE %> - Used for comments. This does nothing.

<%# 'hello world' %>

Live Binding

EJS allows live binding by wrapping magic tag content within a function. When attr() is called
to update an observable object, these functions are executed to return the new value.

// Suppose an observable "foo":
var foo = new CanMap({
bar: 'baz'
});
// Suppose also, the above observable is passed to our view:
<%= foo.attr('bar') %>
// EJS locates the magic tag and turns the above into:
function() { return foo.attr('bar'); }
// As "foo" is updated using attr(), this function is called again to
// render the view with the new value.

This means that each function tag has a closure will reference variables in it's
parent functions. This can cause problems if you don't understand closures in
JavaScript. For example, the following binding does not work:

Advanced Live Binding

Once you get the hang of how EJS works, it makes live-binding of complex
calculations possible. The following extends a [can.Model.List] to suppot a completed method that
returns the total number of completed items in the list. It can be used in a template like:

completed listens on changes to the list (via this.attr('length')) and
each item's 'completed' property. EJS keeps track of which observe/attribute pairs are called
by .complete(). If they change, EJS will automatically unbind.

Element Callbacks

If a function is returned by the <%= %> or <%== %> magic tags within an element’s tag like:

The function is called back with the HTMLElement as the first argument. This is useful to initialize functionality on an element within the view. This is so common that EJS supports ES5 arrow functions that get passed the NodeList wrapped element. Using jQuery, this lets you write the above callback as:

<div <%= (el) -> el.hide() %> >
Hello
</div>

This technique is commonly used to add data, especially model instances, to an element like: