Permalink
Browse files

add docs

  • Loading branch information...
1 parent fed029f commit c27df5df598fff4c7186f3a32ca8451d7acc0e9e @andreypopp committed Mar 6, 2013
Showing with 732 additions and 3 deletions.
  1. +1 −0 .gitignore
  2. +242 −3 README.md
  3. +15 −0 docs/Makefile
  4. +123 −0 docs/app.css
  5. +86 −0 docs/app.sass
  6. +1 −0 docs/footer.html
  7. +5 −0 docs/head.html
  8. +259 −0 docs/index.html
View
1 .gitignore
@@ -1,2 +1,3 @@
node_modules
components
+.sass-cache
View
245 README.md
@@ -1,4 +1,243 @@
-# Backbone.ViewDSL — declarative view technology for Backbone
+# Backbone.ViewDSL
-Backbone.ViewDSL provides declarative view technology and model driven views on
-top of Backbone library.
+Backbone.ViewDSL provides declarative view technology on top of Backbone.
+
+The main feature of Backbone.ViewDSL is an extensible DOM templating engine
+which allows you to
+
+ * Interpolate string or DOM values
+ * Instantiate sub-views directly from inside templates
+ * Bind data to DOM text nodes or element attributes
+ * Automatically setup references for DOM nodes being rendered
+ * Create custom directives as custom HTML tags or attributes
+
+To give a taste of these features there's a basic example
+
+ class App extends Backbone.ViewDSL.View
+ template: """
+ <h1 element-id="$header">{{bind:user.name}}'s todos</h1>
+ <view name="views:UserCard" model="user"></view>
+ <foreach collection="todos">
+ <view name="views:TodoView"></view>
+ </foreach>
+ """
+
+This work was mainly inspired by [Angular.js][] but tries to stay as close to
+Backbone style as possible so it is very easy to use in your application in a
+completely non-intrusive way.
+
+[Angular.js]: http://angularjs.org/
+
+## Installation
+
+You can grab [compiled JavaScript code][code] from the [repo][] or use `npm`:
+
+ % npm install backbone.viewdsl
+
+ or `bower` package managers:
+
+ % bower install backbone.viewdsl
+
+The only dependencies are jQuery, Backbone and underscore.js — if you use one of
+the package managers they will be installed automatically, otherwise you should
+download them by hand.
+
+Backbone.ViewDSL designed to work in CommonJS environment as well as with any
+available AMD loader (such as RequireJS). If you don't use nor AMD neither
+CommonJS loading strategies then all the public API will be available through
+the `Backbone.ViewDSL` browser global.
+
+[code]: https://raw.github.com/andreypopp/backbone.viewdsl/master/backbone.viewdsl.js
+[repo]: https://github.com/andreypopp/backbone.viewdsl
+
+## Basic usage
+
+The main usage pattern is exposed via `Backbone.ViewDSL.View` subclass of
+`Backbone.View` with a custom implementation of `render()` method.
+
+Usually you want to define a new subclass of it and set a `template` attribute:
+
+ class Message extends Backbone.ViewDSL.View
+ template: """
+ {{greeting}}, {{options.name}}!
+ """
+
+ greeting: ->
+ 'Hello'
+
+ view = new Message(name: 'World')
+ view.render()
+
+This template uses string interpolation to insert `options.name` value and a
+result of `greeting()` method call inside the DOM text node. That way view's
+`el` DOM element will have a form of `<div>Hello, World!</div>`.
+
+Templates are always rendered in the context of a view so we can reference any
+view's attribute inside them or call any methods without arguments. If you need
+to reach some nested attribute or method then you can use usual dotted-path like
+`a.b.c`.
+
+## Sub-views instantiation
+
+Backbone doesn't have an opinion on how to manage view hierarchies inside your
+application so usually you cook something by yourself.
+
+Backbone.ViewDSL tries to make this task a lot easier by providing you with a
+*view* directive which allows instantiating sub-views right from inside
+templates. The directive can be used as a `<view>` DOM element or `view` DOM
+attribute.
+
+The example would be
+
+ class App extends Backbone.ViewDSL.View
+ template: """
+ <view name="views.Sidebar" model="user" id="sidebar"></view>
+ <footer view="views.Footer" view-model="user" view-id="footer"></footer>
+ """
+
+ app = new App
+ app.render()
+
+This snippet of code alone makes a lot of things under the hood.
+
+View `views.Sidebar` will be rendered and `app.user` will be passed into its
+constructor as a `model` option. After that rendered view will be stored as
+`app.sidebar` attribute.
+
+There's a bit different story with `views.Footer` — it also gets `app.user` as a
+constructor `model` option but instead of creating new DOM node for the view
+itself it will reuse `<footer>` element. That could be useful if you don't know
+before with what kind of element view will be used.
+
+Without using Backbone.ViewDSL all of these would look like this:
+
+ class App extends Backbone.View
+
+ render: ->
+ this.sidebar = new Sidebar(model: this.user)
+ this.sidebar.render()
+ this.$el.append(this.sidebar.$el)
+
+ this.footer = new Footer(model: this.user, tagName: 'footer')
+ this.footer.render()
+ this.$el.append(this.footer.$el)
+
+The variant which uses `Backbone.ViewDSL.ViewDSL` looks a lot cleaner, doesn't
+it? Also `Backbone.ViewDSL.View` keeps track of all instantiated sub-views and
+handles its disposal so no memory leaks will happen.
+
+## String and DOM values interpolation
+
+As it was already shown Backbone.ViewDSL allows you to insert specific
+bits of text inside templates. But what's more interesting — you can also insert
+entire DOM elements into templates, even with attached event handlers.
+
+ class View extends Backbone.ViewDSL.ViewDSL
+ template: """
+ {{element}} {{jquery}}
+ """
+ element: ->
+ document.createElement('div')
+ jquery: ->
+ $('<div>').addClass('klass')
+
+Rendered view will have `<div></div> <div class="klass"></div>` as its content.
+As you can see you can also insert jQuery objects into template.
+
+## Referencing DOM nodes
+
+Sometimes you need to reference DOM element from recently rendered template —
+you can select it by using `this.$` method call but a better way would be to use
+`element-id` attribute directive.
+
+ class View extends Backbone.ViewDSL.View
+ template: """
+ <div class="main" element-id="block"></div>
+ """
+
+ view = new View
+ view.render()
+
+That way rendered `<div>` element will be available as `view.block` attribute.
+
+## Other built-in directives
+
+There are a couple of other built-in directives — `attr-*` and `class-*`
+wildcard directives and `show-if` directive.
+
+The `attr-*` directive can be used to attach attributes to DOM elements based on
+some view's value. For example given the template
+
+ <img attr-src="model.imageURL">
+
+We will get `src` attribute set to value of `model.imageURL` view's attribute.
+There's also a special case for attributes which has boolean interpretation
+(`checked`, `contenteditable` and so on...) — if expression evaluates to
+`Boolean` value then attribute will be present if value is `true` in case of
+`false` value attribute will not be rendered.
+
+ class View extends Backbone.ViewDSL.View
+ template: """
+ <h1 attr-contenteditable="isEditable">title</h1>
+ """
+ isEditable: ->
+ this.model.get('isEditable') and this.user.canEdit(this.model)
+
+Note that `isEditable` method returns boolean value.
+
+The `class-*` wildcard directive works like a `attr-*` directive but instead
+regulates if element should receive an additional CSS class based on some view's
+attribute or method.
+
+ class View extends Backbone.ViewDSL.View
+ template: """
+ <h1 class-editable="isEditable">title</h1>
+ """
+ isEditable: ->
+ this.model.get('isEditable') and this.user.canEdit(this.model)
+
+In this example, `<h1>` will have class `editable` if and only if `isEditable`
+method evaluates to `true`.
+
+The last of the built-in directives — `show-if` controls if element is visible
+based on some expression which evaluates to boolean value:
+
+ <div show-if="this.collection.isEmpty">No items"</div>
+
+The `<div>` element will be displayed only if `this.collection.isEmpty()`
+evaluates to `true`. Methods `$.show()` and `$.hide()` are used to
+correspondingly show and hide elements.
+
+## Data-binding
+
+You want your views to react to underlying data changes but manually maintaining
+a set of `change` event handlers isn't an option.
+
+For that reason a part of Backbone.ViewDSL directives like `attr-*`, `class-*`
+and `show-if` as well as interpolation mechanism allows you to bind their action
+on data changes and react to them accordingly.
+
+To turn data-binding on you have to prefix all expressions with `bind:`
+modifier:
+
+ class View extends Backbone.ViewDSL.View
+ redAllowed: true
+
+ template: """
+ <div class-red="bind:isRed">Hello, {{bind:model.name}}!</div>
+ """
+
+ isRed: ->
+ this.model.get('red') and this.redAllowed
+
+ view = new View(model: new Backbone.Model(name: 'World', red: false))
+ view.render()
+
+That way rendered view will react to data changes according to directive
+actions.
+
+## Creating custom directives
+
+## Rendering collections
+
+## Parametrizable views
View
15 docs/Makefile
@@ -0,0 +1,15 @@
+all: index.html app.css
+
+watch:
+ watch -n0.3 $(MAKE) all
+
+index.html: ../README.md
+ @cat head.html > $@
+ @redcarpet --smarty ../README.md >> $@
+ @cat footer.html >> $@
+
+app.css: app.sass
+ @sass --compass $< > $@
+
+clean:
+ rm -f app.css index.html
View
123 docs/app.css
@@ -0,0 +1,123 @@
+@import url(http://fonts.googleapis.com/css?family=Open+Sans:700,300&subset=latin,cyrillic-ext);
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font: inherit;
+ font-size: 100%;
+ vertical-align: baseline; }
+
+html {
+ line-height: 1; }
+
+ol, ul {
+ list-style: none; }
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+caption, th, td {
+ text-align: left;
+ font-weight: normal;
+ vertical-align: middle; }
+
+q, blockquote {
+ quotes: none; }
+ q:before, q:after, blockquote:before, blockquote:after {
+ content: "";
+ content: none; }
+
+a img {
+ border: none; }
+
+article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
+ display: block; }
+
+body {
+ height: 100%;
+ width: 100%;
+ font-family: "Open Sans", sans-serif;
+ background: #f4f4f4;
+ color: #424242; }
+
+header, p, ul, ol, aside, figure, article, pre {
+ margin: 1em 0; }
+
+li {
+ margin: 0.5em 0; }
+
+em {
+ border-bottom: 1px dotted #5c5c5c;
+ color: #5c5c5c;
+ cursor: help; }
+
+pre {
+ margin-left: 3em; }
+
+pre,
+code {
+ color: #424242;
+ font-family: Menlo, Monaco, "Bitstream Mono", monospace;
+ font-size: 10pt;
+ line-height: 1.25em; }
+
+p code {
+ margin: 0 0.3em;
+ padding: 0 0.3em;
+ background: white;
+ white-space: nowrap; }
+
+ul li {
+ margin-left: 1.5em;
+ list-style-type: square; }
+
+ol li {
+ margin-left: 1.5em;
+ list-style-type: decimal; }
+
+p {
+ line-height: 1.4em; }
+
+a {
+ text-decoration: none;
+ padding: 0 0.1em;
+ color: #3299bb; }
+ a:hover {
+ color: #f4f4f4;
+ background: #3299bb; }
+
+section {
+ margin: 2em 0; }
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: bold;
+ color: #3299bb;
+ margin-bottom: 1em;
+ margin-top: 2em;
+ text-transform: uppercase;
+ margin-left: -40px; }
+
+h1 {
+ font-size: 22pt; }
+
+h2 {
+ font-size: 16pt; }
+
+.main {
+ width: 600px;
+ margin: 0 auto;
+ padding: 80px 0;
+ padding-left: 40px; }
View
86 docs/app.sass
@@ -0,0 +1,86 @@
+@import compass/reset
+@import url(http://fonts.googleapis.com/css?family=Open+Sans:700,300&subset=latin,cyrillic-ext)
+
+$bg: #f4f4f4
+$color: #424242
+$acolor: #3299BB
+$vmargin: 1em
+$header-shift: 40px
+
+body
+ height: 100%
+ width: 100%
+ font-family: 'Open Sans', sans-serif
+ background: $bg
+ color: $color
+
+header, p, ul, ol, aside, figure, article, pre
+ margin: $vmargin 0
+
+li
+ margin: $vmargin/2 0
+
+em
+ border-bottom: 1px dotted lighten($color, 10%)
+ color: lighten($color, 10%)
+ cursor: help
+
+pre
+ margin-left: 3em
+
+pre,
+code
+ color: $color
+ font-family: Menlo, Monaco, "Bitstream Mono", monospace
+ font-size: 10pt
+ line-height: 1.25em
+
+p code
+ margin: 0 0.3em
+ padding: 0 0.3em
+ background: lighten($bg, 20%)
+ white-space: nowrap
+
+ul li
+ margin-left: 1.5em
+ list-style-type: square
+
+ol li
+ margin-left: 1.5em
+ list-style-type: decimal
+
+p
+ line-height: 1.4em
+
+a
+ text-decoration: none
+ padding: 0 0.1em
+
+ color: $acolor
+
+ &:hover
+ color: $bg
+ background: $acolor
+
+section
+ margin: $vmargin*2 0
+
+h1, h2, h3, h4, h5, h6
+ font-weight: bold
+ color: $acolor
+ margin-bottom: $vmargin
+ margin-top: $vmargin * 2
+ text-transform: uppercase
+ margin-left: - $header-shift
+
+h1
+ font-size: 22pt
+
+h2
+ font-size: 16pt
+
+.main
+ width: 600px
+ margin: 0 auto
+ padding: 80px 0
+ padding-left: $header-shift
View
1 docs/footer.html
@@ -0,0 +1 @@
+</div>
View
5 docs/head.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Backbone.ViewDSL</title>
+<link rel="stylesheet" href="app.css">
+<div class="main">
View
259 docs/index.html
@@ -0,0 +1,259 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Backbone.ViewDSL</title>
+<link rel="stylesheet" href="app.css">
+<div class="main">
+<h1>Backbone.ViewDSL</h1>
+
+<p>Backbone.ViewDSL provides declarative view technology on top of Backbone.</p>
+
+<p>The main feature of Backbone.ViewDSL is an extensible DOM templating engine
+which allows you to</p>
+
+<ul>
+<li>Interpolate string or DOM values</li>
+<li>Instantiate sub-views directly from inside templates</li>
+<li>Bind data to DOM text nodes or element attributes</li>
+<li>Automatically setup references for DOM nodes being rendered</li>
+<li>Create custom directives as custom HTML tags or attributes</li>
+</ul>
+
+<p>To give a taste of these features there&#39;s a basic example</p>
+
+<pre><code>class App extends Backbone.ViewDSL.View
+ template: &quot;&quot;&quot;
+ &lt;h1 element-id=&quot;$header&quot;&gt;{{bind:user.name}}&#39;s todos&lt;/h1&gt;
+ &lt;view name=&quot;views:UserCard&quot; model=&quot;user&quot;&gt;&lt;/view&gt;
+ &lt;foreach collection=&quot;todos&quot;&gt;
+ &lt;view name=&quot;views:TodoView&quot;&gt;&lt;/view&gt;
+ &lt;/foreach&gt;
+ &quot;&quot;&quot;
+</code></pre>
+
+<p>This work was mainly inspired by <a href="http://angularjs.org/">Angular.js</a> but tries to stay as close to
+Backbone style as possible so it is very easy to use in your application in a
+completely non-intrusive way.</p>
+
+<h2>Installation</h2>
+
+<p>You can grab <a href="https://raw.github.com/andreypopp/backbone.viewdsl/master/backbone.viewdsl.js">compiled JavaScript code</a> from the <a href="https://github.com/andreypopp/backbone.viewdsl">repo</a> or use <code>npm</code>:</p>
+
+<pre><code>% npm install backbone.viewdsl
+</code></pre>
+
+<p>or <code>bower</code> package managers:</p>
+
+<pre><code>% bower install backbone.viewdsl
+</code></pre>
+
+<p>The only dependencies are jQuery, Backbone and underscore.js — if you use one of
+the package managers they will be installed automatically, otherwise you should
+download them by hand.</p>
+
+<p>Backbone.ViewDSL designed to work in CommonJS environment as well as with any
+available AMD loader (such as RequireJS). If you don&#39;t use nor AMD neither
+CommonJS loading strategies then all the public API will be available through
+the <code>Backbone.ViewDSL</code> browser global.</p>
+
+<h2>Basic usage</h2>
+
+<p>The main usage pattern is exposed via <code>Backbone.ViewDSL.View</code> subclass of
+<code>Backbone.View</code> with a custom implementation of <code>render()</code> method.</p>
+
+<p>Usually you want to define a new subclass of it and set a <code>template</code> attribute:</p>
+
+<pre><code>class Message extends Backbone.ViewDSL.View
+ template: &quot;&quot;&quot;
+ {{greeting}}, {{options.name}}!
+ &quot;&quot;&quot;
+
+ greeting: -&gt;
+ &#39;Hello&#39;
+
+view = new Message(name: &#39;World&#39;)
+view.render()
+</code></pre>
+
+<p>This template uses string interpolation to insert <code>options.name</code> value and a
+result of <code>greeting()</code> method call inside the DOM text node. That way view&#39;s
+<code>el</code> DOM element will have a form of <code>&lt;div&gt;Hello, World!&lt;/div&gt;</code>.</p>
+
+<p>Templates are always rendered in the context of a view so we can reference any
+view&#39;s attribute inside them or call any methods without arguments. If you need
+to reach some nested attribute or method then you can use usual dotted-path like
+<code>a.b.c</code>.</p>
+
+<h2>Sub-views instantiation</h2>
+
+<p>Backbone doesn&#39;t have an opinion on how to manage view hierarchies inside your
+application so usually you cook something by yourself.</p>
+
+<p>Backbone.ViewDSL tries to make this task a lot easier by providing you with a
+<em>view</em> directive which allows instantiating sub-views right from inside
+templates. The directive can be used as a <code>&lt;view&gt;</code> DOM element or <code>view</code> DOM
+attribute.</p>
+
+<p>The example would be</p>
+
+<pre><code>class App extends Backbone.ViewDSL.View
+ template: &quot;&quot;&quot;
+ &lt;view name=&quot;views.Sidebar&quot; model=&quot;user&quot; id=&quot;sidebar&quot;&gt;&lt;/view&gt;
+ &lt;footer view=&quot;views.Footer&quot; view-model=&quot;user&quot; view-id=&quot;footer&quot;&gt;&lt;/footer&gt;
+ &quot;&quot;&quot;
+
+app = new App
+app.render()
+</code></pre>
+
+<p>This snippet of code alone makes a lot of things under the hood.</p>
+
+<p>View <code>views.Sidebar</code> will be rendered and <code>app.user</code> will be passed into its
+constructor as a <code>model</code> option. After that rendered view will be stored as
+<code>app.sidebar</code> attribute.</p>
+
+<p>There&#39;s a bit different story with <code>views.Footer</code> — it also gets <code>app.user</code> as a
+constructor <code>model</code> option but instead of creating new DOM node for the view
+itself it will reuse <code>&lt;footer&gt;</code> element. That could be useful if you don&#39;t know
+before with what kind of element view will be used.</p>
+
+<p>Without using Backbone.ViewDSL all of these would look like this:</p>
+
+<pre><code>class App extends Backbone.View
+
+ render: -&gt;
+ this.sidebar = new Sidebar(model: this.user)
+ this.sidebar.render()
+ this.$el.append(this.sidebar.$el)
+
+ this.footer = new Footer(model: this.user, tagName: &#39;footer&#39;)
+ this.footer.render()
+ this.$el.append(this.footer.$el)
+</code></pre>
+
+<p>The variant which uses <code>Backbone.ViewDSL.ViewDSL</code> looks a lot cleaner, doesn&#39;t
+it? Also <code>Backbone.ViewDSL.View</code> keeps track of all instantiated sub-views and
+handles its disposal so no memory leaks will happen.</p>
+
+<h2>String and DOM values interpolation</h2>
+
+<p>As it was already shown Backbone.ViewDSL allows you to insert specific
+bits of text inside templates. But what&#39;s more interesting — you can also insert
+entire DOM elements into templates, even with attached event handlers.</p>
+
+<pre><code>class View extends Backbone.ViewDSL.ViewDSL
+ template: &quot;&quot;&quot;
+ {{element}} {{jquery}}
+ &quot;&quot;&quot;
+ element: -&gt;
+ document.createElement(&#39;div&#39;)
+ jquery: -&gt;
+ $(&#39;&lt;div&gt;&#39;).addClass(&#39;klass&#39;)
+</code></pre>
+
+<p>Rendered view will have <code>&lt;div&gt;&lt;/div&gt; &lt;div class=&quot;klass&quot;&gt;&lt;/div&gt;</code> as its content.
+As you can see you can also insert jQuery objects into template.</p>
+
+<h2>Referencing DOM nodes</h2>
+
+<p>Sometimes you need to reference DOM element from recently rendered template —
+you can select it by using <code>this.$</code> method call but a better way would be to use
+<code>element-id</code> attribute directive.</p>
+
+<pre><code>class View extends Backbone.ViewDSL.View
+ template: &quot;&quot;&quot;
+ &lt;div class=&quot;main&quot; element-id=&quot;block&quot;&gt;&lt;/div&gt;
+ &quot;&quot;&quot;
+
+view = new View
+view.render()
+</code></pre>
+
+<p>That way rendered <code>&lt;div&gt;</code> element will be available as <code>view.block</code> attribute.</p>
+
+<h2>Other built-in directives</h2>
+
+<p>There are a couple of other built-in directives — <code>attr-*</code> and <code>class-*</code>
+wildcard directives and <code>show-if</code> directive.</p>
+
+<p>The <code>attr-*</code> directive can be used to attach attributes to DOM elements based on
+some view&#39;s value. For example given the template</p>
+
+<pre><code>&lt;img attr-src=&quot;model.imageURL&quot;&gt;
+</code></pre>
+
+<p>We will get <code>src</code> attribute set to value of <code>model.imageURL</code> view&#39;s attribute.
+There&#39;s also a special case for attributes which has boolean interpretation
+(<code>checked</code>, <code>contenteditable</code> and so on&hellip;) — if expression evaluates to
+<code>Boolean</code> value then attribute will be present if value is <code>true</code> in case of
+<code>false</code> value attribute will not be rendered.</p>
+
+<pre><code>class View extends Backbone.ViewDSL.View
+ template: &quot;&quot;&quot;
+ &lt;h1 attr-contenteditable=&quot;isEditable&quot;&gt;title&lt;/h1&gt;
+ &quot;&quot;&quot;
+ isEditable: -&gt;
+ this.model.get(&#39;isEditable&#39;) and this.user.canEdit(this.model)
+</code></pre>
+
+<p>Note that <code>isEditable</code> method returns boolean value.</p>
+
+<p>The <code>class-*</code> wildcard directive works like a <code>attr-*</code> directive but instead
+regulates if element should receive an additional CSS class based on some view&#39;s
+attribute or method.</p>
+
+<pre><code>class View extends Backbone.ViewDSL.View
+ template: &quot;&quot;&quot;
+ &lt;h1 class-editable=&quot;isEditable&quot;&gt;title&lt;/h1&gt;
+ &quot;&quot;&quot;
+ isEditable: -&gt;
+ this.model.get(&#39;isEditable&#39;) and this.user.canEdit(this.model)
+</code></pre>
+
+<p>In this example, <code>&lt;h1&gt;</code> will have class <code>editable</code> if and only if <code>isEditable</code>
+method evaluates to <code>true</code>.</p>
+
+<p>The last of the built-in directives — <code>show-if</code> controls if element is visible
+based on some expression which evaluates to boolean value:</p>
+
+<pre><code>&lt;div show-if=&quot;this.collection.isEmpty&quot;&gt;No items&quot;&lt;/div&gt;
+</code></pre>
+
+<p>The <code>&lt;div&gt;</code> element will be displayed only if <code>this.collection.isEmpty()</code>
+evaluates to <code>true</code>. Methods <code>$.show()</code> and <code>$.hide()</code> are used to
+correspondingly show and hide elements.</p>
+
+<h2>Data-binding</h2>
+
+<p>You want your views to react to underlying data changes but manually maintaining
+a set of <code>change</code> event handlers isn&#39;t an option.</p>
+
+<p>For that reason a part of Backbone.ViewDSL directives like <code>attr-*</code>, <code>class-*</code>
+and <code>show-if</code> as well as interpolation mechanism allows you to bind their action
+on data changes and react to them accordingly.</p>
+
+<p>To turn data-binding on you have to prefix all expressions with <code>bind:</code>
+modifier:</p>
+
+<pre><code>class View extends Backbone.ViewDSL.View
+ redAllowed: true
+
+ template: &quot;&quot;&quot;
+ &lt;div class-red=&quot;bind:isRed&quot;&gt;Hello, {{bind:model.name}}!&lt;/div&gt;
+ &quot;&quot;&quot;
+
+ isRed: -&gt;
+ this.model.get(&#39;red&#39;) and this.redAllowed
+
+view = new View(model: new Backbone.Model(name: &#39;World&#39;, red: false))
+view.render()
+</code></pre>
+
+<p>That way rendered view will react to data changes according to directive
+actions.</p>
+
+<h2>Creating custom directives</h2>
+
+<h2>Rendering collections</h2>
+
+<h2>Parametrizable views</h2>
+</div>

0 comments on commit c27df5d

Please sign in to comment.