dna.js

An uncomplicated user interface library for semantic templates

Fork me on GitHub

Documentation

For an overview of using dna.js, see the Bookstore Example.

For richer examples, view the HTML source of the project visual specification runner.

Terminology and Browser Support

Terminology

Template:
An HTML element whose clones are injected with data from JavaScript objects.  The element has the dna-template class.
Data Field:
Data fields identify where in the template data is to be injected during the cloning process.  The name of the data field (object property) is surrounded by a pair of double tildes (example: ~~author~~).  Mustache notation with curly braces ({{ and }}) is also supported.
Clone:
A DOM element that is made by copying a template. The template name is added as each clone's class name.

Browser Support

Web Browsers:
dna.js supports Chrome, Firefox, IE/Edge, Opera, and Safari.  It also runs on Node.js with jsdom.
Versions:
dna.js requires jQuery 2.2 or above, and it has the same system requirements and browser support as the version of jQuery you use.

Setup JS and CSS Assets

  1. CDN
  2. Install with npm
  3. Install with webpack
  4. Rails Assets

Get started by including the JavaScript and CSS files into your project.

CDN

The jsDelivr CDN makes it easy to get started.

Load CSS file

            <link rel=stylesheet href=https://cdn.jsdelivr.net/npm/dna.js@1.3/dna.css>
         
Load JavaScript libraries

            <script src=https://cdn.jsdelivr.net/npm/jquery@3.2/dist/jquery.min.js></script>
            <script src=https://cdn.jsdelivr.net/npm/dna.js@1.3/dna.min.js></script>
         

Alternatively, you can use one of the methods below to download the dna.js files into a folder in your project.

Install with npm

npm can download the assets to your project's node_modules folder.

npm

            $ npm install dna.js --save-prod
         

You can also run dna.js headless (no browser) on Node.js with the DOM provided by jsdom.  See the sample project: dnajs-node-jsdom-starter

Install with webpack

webpack treats the dna.js library as a module.  Use require statements in your application to pull in the library's CSS and JavaScript.

Then use dna.registerContext() to expose your application so its functions can be used as callbacks from web pages.

webpack

            require('dna.js/dna.css');
            var $ = require('jquery');
            var dna = require('dna.js')(window, $);

            var myApp = {
               doSomething: function() { ... }
               };
            dna.registerContext('myApp', myApp);
         

Check out the sample webpack projects dnajs-webpack-starter and dnajs-webpack-to-do-app.

Rails Assets

Rails projects can download dna.js directly from the Rails Assets repository.

Gemfile

            source "https://rails-assets.org" do
               gem "rails-assets-dna.js"
            end
         
application.css

            @import "dna.js";
         
application.js

            //= require jquery3
            //= require dna.js
         

HTML — Classes, Fields, Attributes, and Properties

Template

Use the class dna-template to indicate a template.  The id attribute of the element is the template name.

Example HTML

            <div id=book class=dna-template>
         

Data Field

Enclose data field names in double tildes.  Each field takes up the entire text part of the HTML node.

Example HTML

            <span>~~title~~</span>
         

The field name refers to the property of the data object.  If the data is a simple literal (string, number, or boolean) rather than an object, use the special name [value] for the field.

Example HTML

            <span>~~[value]~~</span>
         

Element Attribute

Attributes are set using the same notation as fields.

Example HTML

            <div id=~~code~~>
         

Note: See Element Attribute (advanced) for alternate ways to set the value of an attribute.

Element Property

Properties are enabled or disabled based on the value of the specified data field.

Example HTML

            <input type=checkbox data-prop-checked=~~isGift~~> Gift Wrap<br>
            <input type=checkbox data-prop-checked=~~isExpress~~> Overnight
         

Valid data attributes for setting a property are data-prop-checked, data-prop-selected, and data-prop-deleted.

Select Option

The current selected option of a select drop-down is set based on the value of the specified data field matching the value attribute of the option element.

Example HTML

            <select data-option=~~category~~>
               <option selected disabled>Select category</option>
               <option value=art>Arts and humanities</option>
               <option value=sci>Science</option>
               <option value=med>Medical</option>
            </select>
         

The data-change attribute can be used in combination with the data-option attribute to fire a callback that gets the current data model whenever the user selects a new drop-down option.

Class

A class can be set just like other attributes.

Example HTML

            <div class=~~type~~>
         

However, the regular attribute technique above wipes out existing classes on the element, so it is generally better to the use the data-class attribute to add a class.

Example HTML (simple data field name)

            <div data-class=~~type~~>
         

If there are two or three names (comma separated), the first name is still the name of the data field but the data field is evaluated for "real" truth.

Example HTML (three names)

            <div data-class=~~onSale,highlight,no-highlight~~>
         

For true, the second name is added to the element as a class name while the class for third name, if provided, is removed.  For false, the third name, if provided, is added to the element as a class name while the class for second name is removed.

NameUseDescription
1stData field nameData for class name or truthiness
2ndClass name (for true)Class added to element for true
3rdClass name (for false)Class added to element for false

Continuing with the example of the onSale data field, the code below would result in the first book containing an element with the class highlight and the second book containing an element with the class no-highlight.

Example HTML

            <div id=book class=dna-template>
               <p data-class=~~onSale,highlight,no-highlight~~>~~title~~</p>
            </div>
         

Example JavaScript

               var books = [
                  { title: 'The DOM',     onSale: true },
                  { title: 'Styling CSS', onSale: false }
                  ];
               dna.clone('book', books);
         

Resulting HTML

            <div class=book>
               <p class=highlight>The DOM</p>
            </div>
            <div class=book>
               <p class=no-highlight>Styling CSS</p>
            </div>
         

Ensemble

Below is an example of a completed template.

Example HTML

            <div id=book class=dna-template>
               <div id=~~code~~>
                  Title: <span>~~title~~</span>
               </div>
               <div data-class=~~type~~>
                  Author: <span>~~author~~</span>
               </div>
            </div>
         

Element Attribute (advanced)

In addition to using regular templating to set attributes, you can prefix data-attr- to the attribute name.

Example HTML for src attribute

            <img src=# data-attr-src=~~url~~ alt=avatar>
         

The prefixing technique enables setting the src attribute for an img element without causing the browser to fetch the image until the src attribute is actually set (adding src=# ensures the HTML is still valid according to the W3 HTML Validator).  This technique can also be used to set the id when the regular technique would result in duplicate IDs.

Similarly, data-attr-type can be used a as a warning free way set HTML5 values for the type attribute on input tags.

Example HTML for date and color fields

            Due date:    <input data-attr-type=date  value=~~dueDate~~><br>
            Cover color: <input data-attr-type=color value=~~coverColor~~>
         

Resulting HTML

            Due date:    <input type=date  value=2017-12-31><br>
            Cover color: <input type=color value=#daa520>
         

Setting HTML5 type values with the data-attr-type attribute avoids browser warnings such as:

JavaScript API

API Overview
  1. dna.clone(name, data, options)
  2. dna.cloneSub(holderClone, arrayField, data, options)
  3. dna.rest.get(name, url, options)
  4. dna.getModel(nameOrClone)
  5. dna.empty(name, options)
  6. dna.refresh(clone, options)
  7. dna.refreshAll(name)
  8. dna.destroy(clone, options)
  9. dna.getClone(elem, options)
  10. dna.getClones(name)
  11. dna.up(elemOrEventOrIndex)
  12. dna.down(elemOrEventOrIndex)
  13. dna.bye(elemOrEventOrIndex)
  14. dna.registerInitializer(callback, options)
  15. dna.clearInitializers()
  16. dna.registerContext(contextName, contextObjectOrFunction)
  17. dna.info()

dna.clone(name, data [, options])

Generates a copy of the template and populates the fields, attributes, and classes from the supplied data.

Parameters:
  • Name of the template to clone.
  • Data to be used for populating the template fields when cloning the template.  If data is an array, the length of the array is the number of clones to be generated.
    • Use the jQuery .fadeIn() effect (default: false).
    • Prepend new clone element (default: false).
    • Number of times to clone the data (default: 1).
    • Inject data as HTML rather than the default text (default: false).
    • Clear out existing clones first (default: false).
    • Container element to move clone into when using nested templates (default: null).
    • Task to mutate (enhance) data before it is used to create a clone.  The form is Function(data) {...}, where data is the data object applied to that clone (default: null).
    • Task to be run at the end of cloning.  The form is Function(elem, data) {...}, where elem is the jQuery object for the clone and data is the data object applied to that clone (default: null).
Example JavaScript

            dna.clone('book', { title: 'The DOM', author: 'Bo' });
         

dna.cloneSub(holderClone, arrayField, data[, options])

Clones a sub-template to append onto an array loop.

Parameters:
  • Clone element that contains the sub-template array loop.
  • Name of data field for an array loop.
  • Data to be used for populating the template fields when cloning the template.  If data is an array, the length of the array is the number of clones to be generated.
    • Use the jQuery .fadeIn() effect (default: false).
Example JavaScript

            var book = { title: 'Interwebz', chapters: ['ARPANET', 'TCP/IP'] };
            var clone = dna.clone('book', book);
            dna.cloneSub(clone, 'chapters', 'CERN');  //append chapter
         

See the Sub-templates (array loops) section for details.

dna.createTemplate(name, html, holder)

Generates a template from an HTML string.

Parameters:
  • Name of the template to clone.
  • HTML string representation of a template.  The html represents a template with exactly one node at its root.  No id or class attributes are required.
  • Container element to hold clones that are created from the template.
Example JavaScript

            var books = [
               { title: 'The DOM' },
               { title: 'Go JavaScript!' },
               { title: 'Styling CSS3' }
               ];
            var html = '<li>~~title~~</li>';
            dna.createTemplate('book', html, $('ol#book-list'));
            dna.clone('book', books);
         

Resulting HTML

            <ol id=book-list>
               <li class=book>The Dom</li>
               <li class=book>Go JavaScript!</li>
               <li class=book>Styling CSS3</li>
            </ol>
         

dna.rest.get(name, url [, options])

Makes a GET request to the url and then generates a copy of the template and populates the fields, attributes, and classes from the JSON response.

Note: This feature is currently experimental with very limited functionality.

Parameters:
  • Name of the template to clone.
  • URL of a REST call that returns data as JSON text (Content-Type: application/json).  See the data field for the dna.clone() method.
    • Use the jQuery .fadeIn() effect (default: false).
    • Prepend new clone element (default: false).
    • Inject data as HTML rather than the default text (default: false).
    • Clear out existing clones first (default: false).
    • Container element to move clone into when using nested templates (default: null).
    • Task to be run at the end of cloning.  The form is Function(elem, data) {...}, where elem is the jQuery object for the clone and data is the data object applied to that clone (default: null).
Example JavaScript

            dna.rest.get('book', 'http://dnajs.org/rest/book/3');
         

The dna.rest.get() method will not create a clone if the REST call returns an error field equal to true.

For example: { "error": true, "message": "Resource not found" }

dna.getModel(clone)

Returns the underlying data of the clone.

Parameters:
  • An element returned from a call to the dna.clone() method.
    • If true, ignore sub-clones and only search for the clone generated from the main template (default: false).
Example JavaScript

            var book = { title: 'The DOM', author: 'Bo' };
            var clone = dna.clone('book', book);
            dna.getModel(clone).title = 'The DOM II';
            dna.refresh(clone);  //updates ui (DOM element) with new title
         

dna.empty(name[, options])

Deletes all clones generated from the template.

Parameters:
  • Name of the template to clone.
    • Use the jQuery .fadeIn() effect (default: false).
Example JavaScript

            dna.empty('book', { fade: true });
         

The dna.empty() method does not delete sub-clones generated from nested templates.

dna.refresh(clone[, options])

Updates an existing clone to reflect changes to the data model.

Parameters:
  • An element returned from a call to the dna.clone() method.
    • New values for the data model.  Only data model fields that are contained in the data option are updated. (default: null).
    • If true, ignore sub-clones and only search for the clone generated from the main template (default: false).
    • Inject data as HTML rather than the default text (default: false).
Example JavaScript

            var book = { title: 'The DOM', author: 'Bo' };
            var clone = dna.clone('book', book);
            dna.getModel(clone).title = 'The DOM II';
            dna.refresh(clone);  //updates ui (DOM element) with new title
         

dna.refreshAll(name)

Updates all the clones of the specified template.

Parameters:
  • Name of the template to clone.
Example JavaScript

            var clone1 = dna.clone('book', { title: 'The DOM' });
            var clone2 = dna.clone('book', { title: 'Styling CSS' });
            dna.getModel(clone1).title = 'The DOM II';    //modified title
            dna.getModel(clone2).title = 'Styling CSS3';  //modified title
            dna.refreshAll('book');  //updates ui with new titles
         

dna.destroy(clone[, options])

Removes an existing clone from the DOM.

Parameters:
  • An element returned from a call to the dna.clone() method.
    • Use the jQuery .fadeIn() effect (default: false).
    • If true, ignore sub-clones and only search for the clone generated from the main template (default: false).
Example JavaScript

            var clone = dna.clone('book', book);
            dna.destroy(clone, { fade: true });
         

Note: If the only option being set is fade to true, it is simpler to user the dna.bye() convenience method.

dna.getClone(elem[, options])

Returns the clone (or sub-clone) for the specified element.

Parameters:
  • Any element within the clone or even the clone itself.
    • If true, ignore sub-clones and only search for the clone generated from the main template (default: false).
Example

            <div id=book class=dna-template>
               <p>~~title~~</p>
               <button data-click=setFavorite>I Like</button>
            </div>
            <script>
               function setFavorite(buttonElem) {
                  dna.getClone(buttonElem).addClass('favorite');
                  }
               dna.clone('book', { title: 'Go JavaScript!' });
            </script>
         

Resulting HTML (before clicking button)

            <div class=book>
               <p>Go JavaScript!</p>
               <button>I Like</button>
            </div>
         

Resulting HTML (after clicking button)

            <div class="book favorite">
               <p>Go JavaScript!</p>
               <button>I Like</button>
            </div>
         

dna.getClones(name)

Returns an array of all the existing clones for the given template.

Parameters:
  • Name of the template to clone.
Example JavaScript

            var books = dna.getClones('book');
         

dna.up(elemOrEventOrIndex)

Smoothly moves a clone up one slot effectively swapping its position with the previous clone.

Parameters:
  • Reference to a jQuery element.
Example: Event callbacks for up and down

            <div id=book class=dna-template>
               <p>~~title~~</p>
               <button data-click=dna.up>Move Up</button>
               <button data-click=dna.down>Move Down</button>
            </div>
         

Users are able to interactively rearrange the clones by clicking the Move Up and Move Down buttons.

dna.down(elemOrEventOrIndex)

Smoothly moves a clone down one slot effectively swapping its position with the next clone.

Parameters:
  • Reference to a jQuery element.

See the example for dna.up().

dna.bye(elemOrEventOrIndex)

Performs a sliding fade out effect on the clone and then removes the element.  The function can be called: 1) as an event callback, 2) from a jQuery loop, or 3) directly with the clone as the parameter.

Parameters:
  • Reference to a jQuery element.
Example 1: Event callback

            <div id=book class=dna-template>
               <p>~~title~~</p>
               <button data-click=dna.bye>Delete Book</button>
            </div>
         
Example 2: jQuery loop

            $('.book.favorite').each(dna.bye);  //deletes all favorite books
         
Example 3: Direct function call

            var clone = dna.clone('book', { title: 'The DOM' });
            dna.bye(clone);  //deletes 'The DOM'
         

Note 1: The element identifying the clone can be a sub-element within the clone or the clone itslef.

Note 2: The clone to be removed can be either a main clone or a sub-clone.

dna.registerInitializer(callback[, options])

Adds a callback function to the list of initializers that are run on all DOM elements.

Parameters:
  • String name of a function or an actual function.
    • CSS selector (default: none).
Example JavaScript

            // Line below replaces:  $('.comment-form').validate();
            dna.registerInitializer('validate', { selector: '.comment-form' });
         

See the Initializers section for details.

dna.clearInitializers()

Deletes all initializers.

Example JavaScript

            dna.registerInitializer('bootstrapSwitch', '.switch');
            dna.clearInitializers();  //undoes previous line
         

See the Initializers section for details.

dna.registerContext(contextName, contextObjectOrFunction)

Registers an application object or individual function to enable it to be used for event callbacks.  Registration is needed when global namespace is not available to dna.js, such as when using webpack to load dna.js as a module.

Parameters:
  • Name of the object or function to register.
  • The object or function being registered.

See the webpack section for more information.

dna.info()

Returns status information about templates on the current web page.

Example JavaScript

            dna.info();
         

The dna.info() method is intended to be called manually from the console to see which templates have been detected and compiled.

Looping

Template Array Loops

Pass in a single object to create one clone.  Pass in an array of objects to create multiple clones.

Example HTML

            <div id=book class=dna-template>~~title~~</div>
         

Example JavaScript

            var books = [
               { title: 'The DOM' },
               { title: 'Interwebz' }
               ];
            dna.clone('book', books);
         

Resulting HTML

            <div class=book>The DOM</div>
            <div class=book>Interwebz</div>
         

Sub-templates (array loops)

Use the data-array attribute to create a sub-template for data fields that are arrays.  Each element of the array will clone the sub-template to generate a sub-clone within the main clone.

Example HTML

            <div id=book class=dna-template>
               Book: <span>~~title~~</span> by
               <span>
                  <span data-array=~~authors~~>~~[value]~~</span>
               </span>
               <div>
                  <div data-array=~~chapters~~>
                     Chapter: <span>~~header~~</span>
                  </div>
               </div>
            </div>
         

Example JavaScript

            var book = {
               title:    'Interwebz',
               authors:  ['Ed', 'Jake', 'Abby'],
               chapters: { header: 'ARPANET', header: 'TCP/IP' }
               };
            dna.clone('book', book);
         

Resulting HTML

            <div class=book>
               Book: <span>Interwebz</span> by
               <span>
                  <span>Ed</span>
                  <span>Jake</span>
                  <span>Abby</span>
               </span>
               <div>
                  <div>
                     Chapter: <span>ARPANET</span>
                  </div>
                  <div>
                     Chapter: <span>TCP/IP</span>
                  </div>
               </div>
            </div>
         

Arrays of Primitives (strings, numbers, booleans)

The special field [value] tells the template to use simple values from an array of primitives.  The special field [count] is the value's index number in the array plus 1.

Example HTML

            <div id=book class=dna-template data-title=~~[value]~~>
               <span>~~[count]~~</span>. <span>~~[value]~~</span>
            </div>
         

Example JavaScript

            var books = ['The DOM', 'Interwebz'];
            dna.clone('book', books);
         

Resulting HTML

            <div class=book data-title="The DOM">
               <span>1</span>. <span>The DOM</span>
            </div>
            <div class=book data-title="Interwebz">
               <span>2</span>. <span>Interwebz</span>
            </div>
         

Separators

Use the data-separator and data-last-separator attributes to insert text between clones.  For example, this feature can put commas and the word "and" between authors in a list.  The two types of separators can be used together or individually.

Example

            <b>Authors:</b>
            <span id=author class=dna-template data-separator=", ">
               <span>~~name~~</span>
            </span>
            <script>
               var authors = [{ name: 'Ed' }, { name: 'Bo'}, { name: 'Jan' }];
               dna.clone('author', authors);
            </script>
         

Result
Authors: Ed, Bo, Jan

Note: For more advanced control, use the classes dna-separator and dna-last-separator on elements within the template.

Example using explicit separator nodes

            <b>Authors:</b>
            <span id=author class=dna-template>
               <span>~~name~~</span><span class=dna-separator>,</span>
               <span class=dna-last-separator>and</span>
            </span>
         

Result
Authors: Ed, Bo and Jan

Events, Callbacks, and Forms

Data Model Transformer

Essential to building semantic templates and keeping JavaScript out of your HTML is having a clean way to mutate (enhance) the data model.  Use the data-transform attribute to declare transformers that implment your business logic.

The transformer function receives the clone's data model so it can modify the model before the clone element is created.

Example HTML

            <div id=book class=dna-template data-transform=enhanceBook>
               <span>~~title~~</span>
               <img src=star.png alt=star data-truthy=~~displayStar~~>
            </div>
         

Example JavaScript

            function enhanceBook(data) {
               data.displayStar = data.rating > 3;  //good books get a star
               }
            var books = [
               { title: 'The DOM',   rating: 2 },
               { title: 'Interwebz', rating: 5 }
               ];
            dna.clone('book', books);
         

Resulting HTML

            <div class=book>
               <span>The DOM</span>
            </div>
            <div class=book>
               <span>Interwebz</span>
               <img src=star.png alt=star>
            </div>
         

Note: The transform function can also be passed as an option when cloning, such as: dna.clone('book', books, { transform: enhanceBook })

Element Callback

Use the data-callback attribute to declare a callback function for a template.  Cloning the template triggers the callback for each new clone, and the clone element is passed into the function.

In the example below, the span node of each new book clone is passed into the blink() function, causing the title to fade in a couple times as if it's blinking at the user.

Example HTML

            <div id=book class=dna-template>
               <span data-callback=blink>~~title~~<span>
            </div>
         
Example JavaScript

            function blink(elem) {
               elem.fadeOut().fadeIn().fadeOut().fadeIn();
               }
         

Note 1: A callback function can also be passed as an option, such as: dna.clone('book', books, { callback: blink });

Note 2: Element callbacks perform a similar function as initializers, but an element callback is specific and an initializer is general.  For example, an element callback is appropriate for an animation or initiating a REST call to retrieve additional data for the element while an initializer is appropriate for configuring tooltips that occur in any element.

Click, Change, and Key Events

Event bindings in dna.js are done with data attributes directly on DOM elements that need to trigger callbacks.  The value assigned to the attribute is the name of the function to be called when the event occurs.  The jQuery element which triggered the event is passed into the callback function as the first parameter, and the event object is passed in as the second parameter.

Element attributes for supported events:
  1. data-click
  2. data-change
  3. data-input
  4. data-key-up
  5. data-key-down
  6. data-key-press
  7. data-enter-key
Example

            <p>Click:  <button data-click=showMsg     value=1>1</button></p>
            <p>Change: <input  data-change=showMsg    value=2></p>
            <p>Input:  <input  data-input=showMsg     value=3></p>
            <p>Up:     <input  data-key-up=showMsg    value=4></p>
            <p>Down:   <input  data-key-down=showMsg  value=5></p>
            <p>Press:  <input  data-key-press=showMsg value=6></p>
            <p>Submit: <input  data-enter-key=showMsg value=7></p>
            <p id=message></p>
            <script>
               function showMsg(elem, event) {
                  var msg = 'Value "' + elem.val() + '" on ' + event.type;
                  $('#message').text(msg).stop().hide().fadeIn();
                  }
            </script>
         

Result (interactive)

Click:

Change:

Input:

Up:

Down:

Press:

Submit:


Note: For text fields input and textarea, use data-smart-update.

Experiment with click events:

Smart Update

Smart update callbacks are run only when a user changes the actual value of a text input, and the calls are throttled to be at least one second apart.

The data-smart-update attribute sets the callback, and the data-smart-throttle attribute sets the throttle rate in milliseconds to override the 1000 millisecond default.

Example

            <input data-smart-update=logNow placeholder="Type here">
            <div id=log-message class=dna-template>
               <code>~~message~~</code>
            </div>
            <script>
               function logNow(elem) {
                  var msg = Date.now() + ': ' + elem.val();
                  dna.clone('log-message', { message: msg }, { fade: true });
                  }
            </script>
         

Result (interactive)
~~message~~

Experiment with smart update events:

Smart update events can be used over WebSockets:
github.com/dnajs/dnajs-smart-update-websockets

screenshot
Example WebSockets server and client showing throttled live updates using dna.js

Jump to page (URL)

Similar to the <a> anchor tag, the data-href attribute redirects the browser to the specified URL when the user clicks the element.

Example

            <button data-href=../book-finder.html>Book Finder</button>
         

Result (interactive)

Add class=external-site to tell the browser to open the link in a new tab (or window).

Data Model Updating on Field Updates

The clone's data model is updated when a user edits or changes an input field.

Input FieldExample
text <input value=~~title~~>
checkbox <input type=checkbox data-prop-checked=~~set~~>
radio button <input type=radio name=cover data-prop-checked=~~set~~>
drop-down <select data-option=~~category~~>

The example below uses event bindings to call a function that reads the data model with dna.getModel().

Example HTML

            <h2>Book Information</h2>
            <div id=book class=dna-template>
               Title: <input value=~~title~~ data-key-up=bookInfo.update>
               ebook: <input type=checkbox data-prop-checked=~~ebook~~
                  data-change=bookInfo.update>
            </div>
            <div>Data: <code id=data>[YOUR MOVE]</code></div>
         

Example JavaScript

            var bookInfo = {
               update: function(elem) {
                  var data = JSON.stringify(dna.getModel(elem));
                  $('#data').text(data).hide().fadeIn();
                  },
               setup: function() {
                  var book = { title: 'Styling CSS', ebook: true };
                  dna.clone('book', book);
                  }
               };
            $(bookInfo.setup);
         

Update data model (interactive)

Book Information

Title:
ebook:

Data: [YOUR MOVE]

Note: While the original data used to clone the template may contain truthy values, the boolean values updated in the data model are set to actual true or false.

Initializers

On a static page where all the HTML is sent in a single HTTP response, any needed element initialization can be done one time just after page load.  For example, the line $('.tooltip').qtip(); could be used to setup all tooltips.  Cloning with dna.js creates elements and adds them to the DOM after the page is loaded, and those new elements also need to be initialized.

When you register your initializer functions, dna.js ensures DOM elements are setup even if the elements are added to the DOM via cloning after the page is loaded.

SelectorExampleInitializer
Yes { selector: '.tooltip' } Immediately run on selected elements (example: $('.tooltip')) and then on new clones
No n/a Only run on new clones

If the registered initializer function is a method on the jQuery element, dna.js will execute the method on the element and use the params option for the parameters.  Otherwise, the element is passed into the function as the first parameter with the params supplied as additional parameters.

Example JavaScript

            var app = {
               setup: function() {

                  function highlight(elem) {
                     elem.css({ backgroundColor: 'gold' });
                     }

                  // Highlight each new clone
                  dna.registerInitializer(highlight);

                  // Setup tooltips for each new clone:  $('.tooltip').qtip();
                  dna.registerInitializer('qtip', { selector: '.tooltip' });

                  // Style each new clone:  $('.gap').css({ padding: '8px' });
                  var options = { selector: '.gap', params: { padding: '8px' } }
                  dna.registerInitializer('css', options);

                  }
               };
            $(app.setup);
         

Note 1: Initializers perform a similar function as element callbacks (data-callback), but an initializer is general to all clones and an element callback is specific to clones of one template.  For example, an initializer is appropriate for configuring tooltips that can occur in any clone.

Note 2: In the event that your application dynamically adds elements to the DOM without using dna.js, it may be necessary to explicitly run the initializers by passing the root element of new elements into: dna.events.runInitializers(root);

Transform Option

The transform option for dna.clone() specifies a transformer function to mutate (enhance) the data model.

The transformer function receives the clone's data model so it can modify the model before the clone element is created.

Example HTML

            <div id=book class=dna-template>
               <span>~~title~~</span>
               <img src=star.png alt=star data-truthy=~~displayStar~~>
            </div>
         

Example JavaScript

            function enhanceBook(data) {
               data.displayStar = data.rating > 3;  //good books get a star
               }
            var books = [
               { title: 'The DOM',   rating: 2 },
               { title: 'Interwebz', rating: 5 }
               ];
            dna.clone('book', books, { transform: enhanceBook });
         

Resulting HTML

            <div class=book>
               <span>The DOM</span>
            </div>
            <div class=book>
               <span>Interwebz</span>
               <img src=star.png alt=star>
            </div>
         

Note: A transformer function can also be specified with the data-transform attribute, such as: <div id=book class=dna-template data-transform=enhanceBook>

Callback Option

The callback option for dna.clone() specifies a callback function.

Once cloning is completed, the callback function is executed and passed the clone element plus the data that was injected into the clone.

Example HTML

            <div id=book class=dna-template>
               ~~title~~
            </div>
         

Example JavaScript

            function applyBkgnd(elem, data) {
               elem.css({ backgroundImage: data.cover });
               };
            var options = { fade: true, callback: applyBkgnd };
            var book = { title: 'Taskmaster', cover: 'url(cover.png)' };
            dna.clone('book', book, options);
         

Resulting HTML

            <div class=book style="background-image: url(cover.png);">
               Taskmaster
            </div>
         

See the line dna.clone('circle', circles, { callback: addStyle }); used to create the dna.js logo.

Note: A callback function can also be specified with the data-callback attribute, such as: <div id=book class=dna-template data-callback=blink>

On Load Functions

Use the data-on-load attribute to initiate a callback function after the document is ready.  The element with the data-on-load attribute is passed into on load function once the HTML is loaded.

Example HTML

            <p data-on-load=blink>
               This paragraph will blink on page load!
            </p>
            <script>
               function blink(elem) {
                  elem.fadeOut().fadeIn().fadeOut().fadeIn();
                  }
            </script>
         

The data-on-load attribute can be used in conjunction with the dna.ui.focus function to auto-focus on an input element.

Structures and Conditional Logic

Object Dot Notation (nested objects)

Use JavaScript object dot notation in field names to reference data fields of nested objects.

Example HTML

            <div id=book class=dna-template>
               First Name: <span>~~author.first~~</span>
            </div>
         

Example JavaScript

            var book = {
               title: 'The DOM',
               author: { first: 'Bo', last: 'Smith' }
               };
            dna.clone('book', book);
         

Resulting HTML

            <div class=book>
               First Name: <span>Bo</span>
            </div>
         

Template Placeholder

A template placeholder is only shown when its corresponding template is empty (has zero clones).  The data-placeholder attribute specifies the name of the template.

Example HTML

            <div class=books>
               <p id=book class=dna-template>~~title~~</p>
            </div>
            <div data-placeholder=book>No books</div>
         

The "No books" message is displayed until at least one book is cloned, and the message will be re-displayed if all the book clones are removed.

Thimblerig (conditional hide and seek logic)

Instead of writing JavaScript to show and hide DOM elements, use an attribute to declare whether the element should be shown or hidden.  dna.js supports four conditionals — two for the existence of a field and two for the "real" truth of a field.

AttributeValueLogic
data-requireData FieldShow element only if specified field has a value
data-missingData FieldShow element only if specified field has no value
data-truthyData FieldShow element only if specified field means true*
data-falseyData FieldShow element only if specified field means false*
Example HTML

            <div id=book class=dna-template>
               <span data-require=~~title~~>~~title~~</span>
               <span data-missing=~~title~~>[not found]</span>
            </div>
         

Example JavaScript

            var books = [
               { author: 'Bo', title: 'The DOM' },
               { author: 'Jan' }
               ];
            dna.clone('book', books);
         

Resulting HTML

            <div class=book>
               <span>The DOM</span>
            </div>
            <div class=book>
               <span>[not found]</span>
            </div>
         
Real Truth

dna.js evaluates if a data field is true or false based on rules designed to match the boolean meaning of data as it would be stored in a database or how the data would be interpreted in a business sense.  For example, the string 'FALSE' is evaluated to the boolean false when determining its "real" truth.

EvaluateExamples
Truthy true, 1, '1', 't', 'T', 'TRue', '77', 77, [5], {}, 'Colbert'
Falsey false, 0, '0', 'f', 'F', 'faLSE', '', [], null, undefined, NaN
Transient Fields

Compact and maintainable code can be written by basing conditionals on transient data fields.

Example HTML

            <p class=warning data-truthy=~~overdue~~>Invoice past due!</p>
         
Example JavaScript

            var invoice = { amount: 125.00, due: 'April 3, 2015' },
            invoice.overdue = new Date(invoice.due).getTime() < Date.now();
            dna.clone('invoice', invoice);
         

In the above example, the invoice data object has an amount field and a due field.  The past due warning is displayed if the boolean field overdue, which is calculated on the fly, is set to true.

Note: Similar to thimblerigs, separators are used to hide and show a delimiter between clones, such as a comma to separate names of authors.

Nested Templates

For additional flexibility, templates can be nested and then explicitly cloned with calls to dna.clone().  A nested template belongs to a holder template, and the specific holder clone must be passed into dna.clone() when cloning a nested template.

View source for spec runner #07.

In most cases, a simple sub-template array loop is the better solution.

Hide a Container Element

Add the class dna-hide to a container element that should not be visible until after a decendant template is cloned.

Example component hidden until after cloning

            <section data-component=bookshelf class=dna-hide>
               <h2>Bookshelf</h2>
               <div>
                  <p id=book class=dna-template>~~title~~</p>
               </div>
            </section>
         

The data-component=bookshelf element is hidden until the book template is cloned, thus preventing the user from seeing the <h2>Bookshelf</h2> heading before there are any books.

Also see: data-placeholder

Making Reusable Components

Defining a Component

A reusable component is named using the data-component attribute on the container element.

The component can be initialized with an on load function (data-on-load) to make a REST call that gets data for a template.  Events with callbacks, such as a click event (data-click), pass back the target element, event object, and the component element.

Bookshelf Component CSS

           [data-component=bookshelf] .my-book {
              width: 25em;
              background-color: plum;
              padding: 5px 15px;
              }
         

Bookshelf Component HTML

            <div data-component=bookshelf data-on-load=bookshelf.setup>
               <h2>Bookshelf</h2>
               <div>
                  <p id=my-book class=dna-template>
                     <span>Title: <b>~~title~~</b></span><br>
                     <span>Author: <b>~~author~~</b></span>
                  </p>
               </div>
               <button data-click=bookshelf.show>Show component name</button>
               <script>
                  var bookshelf = {
                     booksUrl: 'http://dnajs.org/rest/book/list/',
                     show: function(elem, event, component) {
                        elem.text(component.data().component + '!');
                        },
                     setup: function(elem) {
                        function handle(data) { dna.clone('my-book', data); }
                        $.getJSON(bookshelf.booksUrl, handle);
                        }
                     };
               </script>
            </div>
         

Result (with three books loaded from REST call)

Bookshelf

Title: ~~title~~
Author: ~~author~~

Panels (UI Tabs)

Panels are content elements associated with menu items.  When the user clicks a menu item, the corresponding panel is displayed (faded in) and the panel element is passed to the callback.  Think of dna.js panels as a minimalistic implementation of jQuery UI tabs stripped of all styling.

Example

The interactive example below displays information for the user selected author.

Example CSS

            [data-component=author] .dna-menu {
               list-style-type: none;
               padding: 0px;
               margin-top: 10px;
               }
            [data-component=author] .menu-item {
               display: inline;
               background-color: lightskyblue;
               border: 2px solid silver;
               border-radius: 5px;
               padding: 5px 10px;
               }
            [data-component=author] .menu-item.selected,
            [data-component=author] .menu-item:hover {
               border-color: dimgray;
               }
         

Example HTML

            <div data-component=author>
               <h2>Author Information</h2>
               Select:
               <ul id=author-info class=dna-menu>
                  <li>Jake</li>
                  <li>Abby</li>
                  <li>Ed</li>
               </ul>
               <div id=author-info-panels class=dna-panels>
                  <section>
                     <h5>Name: Jake</h5>
                     <p>Publisher: O'Reilly</p>
                     <p>Agent: William and Associates</p>
                  </section>
                  <section>
                     <h5>Name: Abby</h5>
                     <p>Publisher: Addison-Wesley</p>
                     <p>Agent: Pro Reps</p>
                  </section>
                  <section>
                     <h5>Name: Ed</h5>
                     <p>Publisher: ASM International</p>
                     <p>Agent: Feven</p>
                  </section>
               </div>
            </div>
         

Result (interactive)

Author Information

Select:
  • Jake
  • Abby
  • Ed
Name: Jake

Publisher: O'Reilly

Agent: William and Associates

Name: Abby

Publisher: Addison-Wesley

Agent: Pro Reps

Name: Ed

Publisher: ASM International

Agent: Feven

Experiment with button navigation panels:

Experiment with drop-down navigation panels:

Template-Driven Panels

The interactive example below uses templates to build the menu and the panels.

Example HTML

            <div data-component=book-catalog data-on-load=bookCatalog.setup>
               <h2>Book Catalog</h2>
               <nav id=book-catalog class=dna-menu>
                  <button id=book-menu-item class=dna-template>
                     ~~[count]~~
                  </button>
               </nav>
               <div id=book-catalog-panels class=dna-panels>
                  <section id=book-panel class=dna-template
                        data-transform=bookCatalog.addCover>
                     <h4>~~title~~</h4>
                     <img src=# data-attr-src=~~cover~~ alt=cover>
                  </section>
               </div>
               <script>
                  var bookCatalog = {
                     data: [
                        { id: 'RLG21IfQDckC', title: 'Designing Apps' },
                        { id: '_xB0PyT9Y24C', title: 'CSS3 Guide' },
                        { id: 'PXa2bby0oQ0C', title: 'The Good Parts' },
                        { id: '4x6Gj_0UHMsC', title: 'Pro jQuery' }
                        ],
                     addCover: function(data) {
                        data.cover = 'https://books.google.com/books?id=' +
                           data.id + '&printsec=frontcover&img=1&zoom=1';
                        },
                     setup: function() {
                        dna.clone('book-menu-item', bookCatalog.data);
                        dna.clone('book-panel',     bookCatalog.data);
                        }
                     };
               </script>
            </div>
         

Result (interactive)

Book Catalog

~~title~~

cover

Panel Routes

Create routes in dna.js by adding a data-hash attribute to each panel element.  The value specified by data-hash becomes the fragment identifier (hash) in the URL.

Optionally, add a data-callback attribute on the menu element to run a function whenever a panel is displayed.  The callback function receives the panel element and fragment identifier (hash) for the currently displayed panel.

Example HTML

               <h2>Publishers</h2>
               <nav id=publisher-info class=dna-menu data-callback=updatePanel>
                  <button>Pearson</button>
                  <button>Shueisha</button>
                  <button>Wiley</button>
               </nav>
               <div id=publisher-info-panels class=dna-panels>
                  <section data-hash=pearson>
                     <h2>Pearson</h2>
                     <p>UK</p>
                  </section>
                  <section data-hash=shueisha>
                     <h2>Shueisha</h2>
                     <p>Japan</p>
                  </section>
                  <section data-hash=wiley>
                     <h2>Wiley</h2>
                     <p>US</p>
                  </section>
               </div>
         

Example JavaScript

            function updatePanel(panel, hash) {
               var url = location.origin + location.pathname + '#' + hash;
               if (!panel.find('a').length)
                  panel.append($('<a>', { text: url, href: url }));
               }
         

Result (interactive)

Publishers

Pearson

UK

Shueisha

Japan

Wiley

US

Styling Panels

It's straightforward to style your panel navigation with CSS.  See the CSS for the examples below: panel-nav.css

Flat tabs
Example HTML for flat tabs styling

               <h2>Book format</h2>
               <nav id=book-format class=dna-menu data-style=flat-tabs>
                  <span>Hardcover</span>
                  <span>Paperback</span>
                  <span>eBook</span>
               </nav>
               <div id=book-format-panels class=dna-panels>
                  <p>Hardcovers are the nicest.</p>
                  <p>Paperbacks are the easiest.</p>
                  <p>EBooks are the future.</p>
               </div>
         

Result (interactive)

Book format

Hardcovers are the nicest.

Paperbacks are the easiest.

eBooks are the future.

Pillbox tabs
Example HTML for pillbox tabs

               <h2>Book type</h2>
               <nav id=book-type class=dna-menu data-style=pillbox-tabs>
                  <span>Action</span>
                  <span>Mystery</span>
                  <span>Sciense Fiction</span>
               </nav>
               <div id=book-type-panels class=dna-panels>
                  <p>Action books</p>
                  <p>Mystery books</p>
                  <p>Science fiction books are the best!</p>
               </div>
         

Result (interactive)

Book type

Action books rock!

Mystery books rule!

Science fiction books are the best!

Example website with pillbox UI tabs: CLABE Validator

Utilities

The utility functions built into dna.js are available to be called directly in the event that they might be generally useful.

Utility Functions Overview
  1. dna.array.find(array, code)
  2. dna.array.fromMap(map, key)
  3. dna.array.last(array)
  4. dna.array.toMap(array, key)
  5. dna.browser.getParams()
  6. dna.pageToken
    dna.pageToken.get(key, value)
    dna.pageToken.put(key, defaultValue)
  7. dna.ui.deleteElem(elemOrEventOrIndex)
  8. dna.ui.focus(elem)
  9. dna.ui.slideFade
    dna.ui.slideFadeDelete(elem)
    dna.ui.slideFadeIn(elem, callback)
    dna.ui.slideFadeOut(elem, callback)
    dna.ui.slideFadeToggle(elem, callback)
  10. dna.ui.slidingFlasher(elem, callback)
  11. dna.ui.smoothHeight
    dna.ui.smoothHeightAnimate(delay, elem)
    dna.ui.smoothHeightSetBaseline(elem)
  12. dna.ui.smoothMove(elem, up)
  13. dna.ui.toElem(elemOrEventOrIndex, that)
  14. dna.util.apply(func, params)
  15. dna.util.printf(formatString, parameters...)
  16. dna.util.realTruth(value)
  17. dna.util.toCamel(kebabCaseStr)
  18. dna.util.toKebab(camelCaseStr)
  19. dna.util.value(data, field)

dna.array.TBD(TBD)

TBD...

dna.pageToken.get(key, defaultValue)

dna.pageToken.put(key, value)

A simple key/value store specific to the page (URL path) that is cleared out when the user's browser session ends.

Parameters:
  • Identifier to lookup data.
  • Data to store.
  • Data to return if the page token is not found.
Example using a direct function call

            var a = dna.pageToken.get('favorite', 0);  //a === 0
            dna.pageToken.put('favorite', 7);
            var b = dna.pageToken.get('favorite', 0);  //b === 7
         

dna.ui.deleteElem(elemOrEventOrIndex)

A flexible function for removing a jQuery element.

Parameters:
  • Reference to a jQuery element.
Example 1: Direct function call

            dna.ui.deleteElem($('.box:first'));  //removes first box
         
Example 2: jQuery callback

            $('.box:last').fadeOut(dna.ui.deleteElem);  //removes last box
         

dna.ui.focus(elem)

Sets focus on the element.

Parameters:
  • An element.
Example HTML

            <label>
               <span>Start typing:</span>
               <input data-on-load=dna.ui.focus>
            </label>
         

dna.ui.slideFadeDelete(elem)

dna.ui.slideFadeIn(elem[, callback])

dna.ui.slideFadeOut(elem[, callback])

dna.ui.slideFadeToggle(elem[, callback])

Various functions to apply the smooth slide plus fade effect.

Parameters:
  • Any element within the clone or even the clone itself.
  • String name of a function or an actual function.
Example JavaScript

            dna.ui.slideFadeDelete($('.box').last());  //removes the last box
            dna.ui.slideFadeIn($('.box').first());  //shows the box
         

dna.ui.slidingFlasher(elem[, callback])

Uses a smooth slide down plus fade in effect on an element if it is hidden or a smooth fade in flash if the element is already visible — intended to display an error message.

Parameters:
  • Any element within the clone or even the clone itself.
  • String name of a function or an actual function.
Example JavaScript

            var elem = $('#msg').text('Error!');
            dna.ui.slidingFlasher(elem);  //slide down
            ...
            dna.ui.slidingFlasher(elem);  //pulse
         

dna.ui.smoothHeightSetBaseline([elem])

dna.ui.smoothHeightAnimate([delay, [elem]])

Smoothly animates the height of a container element from a beginning height to a final height.

If no container element (elem) is specified, the <body> element will be used for the baseline and the animation will use the previously set baseline.

The animation start delay (default is 50 milliseconds) allows time for the container to be drawn.

Usage steps:
  1. Call dna.ui.smoothHeightSetBaseline() to establish the initial height of the container.
  2. Insert (show) and remove (hide) multiple elements within the container.
  3. Call dna.ui.smoothHeightAnimate() to smoothly adjust the container element to its new height.
Parameters:
  • An element.
  • Time in milliseconds to wait before performing operation.
Smooth container of chapters

            Number of chapters:<br>
            <input type=range value=10
               data-on-load=makeChapters data-change=smooth>
            <div id=smooth-container>
               <button id=chapter-box class=dna-template>~~[count]~~</button>
            </div>
            <script>
               function makeChapters(range) {
                  var options = { empty: true, clones: +range.val() };
                  dna.clone('chapter-box', {}, options);
                  }
               function smooth(range) {
                  dna.ui.smoothHeightSetBaseline($('#smooth-container'));
                  makeChapters(range);
                  dna.ui.smoothHeightAnimate();
                  }
            </script>
         

Result (interactive)
Number of chapters:

dna.ui.smoothMove(elem, up)

Uses animation to smoothly slide an element up or down one slot amongst its siblings.

Parameters:
  • Any element within the clone or even the clone itself.
  • Direction to move element is up (true) or down (false).
Example

            <ol>
               <li>The DOM</li>
               <li id=favorite>Go JavaScript!</li>
               <li>Styling CSS3</li>
            </ol>
            <script>dna.ui.smoothMove($('#favorite'), true);</script>
         

The book Go JavaScript! will be first on the list after smoothMove() has executed.

dna.ui.toElem(elemOrEventOrIndex, that)

A flexible way to get the jQuery element whether it is passed in directly, the target of an event, or comes from the jQuery context.

Parameters:
  • Reference to a jQuery element.
  • this.
Example JavaScript

            function logFadeDone(e) {
               console.log('Element faded out:', dna.ui.toElem(e, this));
               }
            $('.box').last().fadeOut(logFadeDone);
         

dna.util.apply(func, params)

Calls a function passing in the provided parameters.

Parameters:
  • String name of a function or an actual function.
  • A single value to pass into the function or an array of values where each element in the array is a parameter passed into the function.
Example JavaScript

            dna.util.apply('app.cart.buy', 7);      //app.cart.buy(7);
            dna.util.apply(Math.max, [7, 21, -3]);  //21;
            dna.util.apply('fadeIn', $('h1'));      //$('h1').fadeIn();
            dna.util.apply('css', [$('h1'), { color: 'red' }]);
            dna.util.apply('css', [$('h1'), 'color', 'gold']);
         

dna.util.printf(formatString, args...)

Builds a formatted string by replacing the format specifiers with the supplied arguments.

Parameters:
  • String with format specifiers ('%s') indicating where arguments are to be inserted.
  • Arguments used to replace format specifiers.
Example JavaScript

            dna.util.printf('%s: %s', 'Lives', 3);  //'Lives: 3'
         

dna.util.realTruth(value)

Return the "real" boolean truth of a value.  Whereas JavaScript truthy an falsey is more about existence, the "real" truth is for evaluating boolean data as it is stored in databases or transmitted in REST calls.

Parameters:
  • Whatever you want to interrogate.
Example JavaScript

            dna.util.realTruth('F');  //false
         

dna.util.toCamel(kebabCaseStr)

Converts a kebab-case string (a code made of lowercase letters and dashes) to camelCase.

Parameters:
  • A string made of lowercase letters and dashes.
Example JavaScript

            dna.util.toCamel('ready-set-go');  //'readySetGo'
         

dna.util.toKebab(camelCaseStr)

Converts a camelCase string to kebab-case (a code made of lowercase letters and dashes).

Parameters:
  • A camelCase string.
Example JavaScript

               dna.util.toKebab('readySetGo');  //'ready-set-go'
         

dna.util.value(data, field)

Returns the value of the field from the data object.

Parameters:
  • Object with fields containing data.
  • Name of a field within the data object (supports object dot notation for nested objects).
Example JavaScript

            var data = { cart: { items: 7 } };
            var count = dna.util.value(data, 'cart.items');  //7
         

Index

List of Classes

  1. dna-hide: Hides a container element until a descendant template is cloned
  2. dna-menu: Mark element as container for panel menu items
  3. dna-panels: Mark element as container for panels
  4. dna-separator: Mark element as a separator for multiple clones
  5. dna-separator-last: Mark element as the last separator
  6. dna-template: Mark an element as a template

List of Data Attributes

  1. data-array: Mark an element as a sub-template array loop
  2. data-attr-{NAME}: Set value of an element attribute
  3. data-callback: Pass element into function when clone is created
  4. data-change: Callback to run on change event
  5. data-class: Add a class to the element
  6. data-click: Callback to run on click event
  7. data-component: Mark a container element as a component
  8. data-enter-key: Callback to run on enter key event
  9. data-falsey: Show element only if field evaluates to false
  10. data-hash: Set the fragment ID (hash) for a panel's URL
  11. data-href: Jumps to the URL (like an <a> link)
  12. data-input: Callback to run on input event
  13. data-key-down: Callback to run on key down event
  14. data-key-press: Callback to run on key press event
  15. data-key-up: Callback to run on key up event
  16. data-missing: Show element only if field us not defined
  17. data-on-load: Pass element into function after HTML is loaded
  18. data-option: Set option in a select drop-down
  19. data-placeholder: Show element only if named template is empty
  20. data-prop-checked: Enable or disable "checked" property
  21. data-prop-disabled: Enable or disable "disabled" property
  22. data-prop-selected: Enable or disable "selected" property
  23. data-require: Show element only if field exists
  24. data-smart-throttle: Delay (milliseconds) between smart update callbacks
  25. data-smart-update: Throttled callback to run on change of an input value
  26. data-transform: Callback to enhance data immediately before cloning
  27. data-truthy: Show element only if field evaluates to true

List of jQuery Plugin Functions

  1. .dna('bye'): Slide fade out then remove
  2. .dna('clone-sub', name, data[, options]): Clone a sub-template
  3. .dna('destroy'[, options]): Remove
  4. .dna('down'): Smoothly move down one slot
  5. .dna('refresh'[, options]): Update to reflect changes to the data model
  6. .dna('up'): Smoothly move up one slot

List of jsFiddle Examples

ExampleLink
Add a Book jsfiddle.net/eo3gpfmo
Book Finder jsfiddle.net/zxb2x6dv
Click Events jsfiddle.net/5dsbvacd
Live Model jsfiddle.net/8gnyLovu
Panels Click jsfiddle.net/uzm44vrf
Panels Drop-downjsfiddle.net/qt95wt46
Smart Updates jsfiddle.net/4a0tpmxp
To Do jsfiddle.net/wo6og0z8

Questions and comments

Tweet your question or comment with or post below.

Disqus