My favorites | Sign in
Project Home Wiki Issues Source
Project Information
Members
Featured
Wiki pages

Distal is a Javascript tool that automatically fills your webpage with data from a JSON source. Freeing you from needing to traverse nodes or create DOM trees just to add dynamic data. Allowing you to focus on the important things such as data logic and webpage design.

Design your webpage as you always have. Then tag your HTML with attributes that describe what data belongs in it. Your designers can customize and update your HTML at anytime. Have your webpage download data in the form of JSON and have Distal fill your webpage with that data.

Objectives

Distal uses a concept created by Zope used in Python projects called Template Attribute Language (TAL), which has the following objectives:

  1. Separation of the user interface and application logic is ensured. Don't lock up your HTML inside strings or dummy textareas!
  2. You can create the user interface using regular HTML files, so that designers can use tools like Dreamweaver without needing backend support.
  3. You no longer need to write a program to generate the user interface nor write a for-loop to populate tables or list items.
  4. The user interface is smart enough to know when to show or hide certain elements depending on the properties of the data.
  5. Make do without ever needing to call getElementById ever again, and never need to call innerHTML or appendChild again.
  6. Distal allows you to validate your HTML against the W3C markup validation tool. And your template text remains as part of your HTML which enables progressive enhancement and helps in search engine optimization.

Download

Click on the Source link above or see the development version or the compressed (3.8k) version

Example:

Say your server returns a JSON object like so:

{
   geotags: [ {id: 1, label: "Work"}, {id: 2, label: "Home"}, {id: 3, label: "Club"} ] 
 }
and your HTML page looks like this:
 <html> 
 Choose a folder to save: <select name="folder"> 
     <option value="" 
         data-qrepeat="folder geotags" 
         data-qattr="value folder.id; text folder.label">Work
 </select> 
 </html> 
Then Distal will take your HTML page and convert it to:
 <html> 
 Choose a folder to save: <select name="folder"> 
     <option value="1">Work
     <option value="2">Home
     <option value="3">Club
 </select> 
 </html> 
And therein lies the beauty of it. As you write your user interface you specify what data goes in it. You don't need to write a separate function to populate your interface.

Demo

Bookmarks Viewer - get real time bookmarks from delicious.com

Test Case - tests the different functions

What does it solve?

Does your web application have so many getElementById calls that you're too embarrassed to admit? Do you spend 80% of your time on getting the interface to work and 20% on data integrity? Have you lost track of which elements are gone and which are new?

Is your user interface over-engineered into widgets just because you want to repeat a template of code for each item of a list? Do you need to update your controller code every time your user interface changes a little?

TAL solved this for Python by acting as the glue that binds HTML with user data; and now it's here in Javascript. It is a meta-language that both designers and programmers know. Programmers pass on a structured object of data in the form of JSON to the interface and the interface knows what properties to take out and where on the page to put it. TAL greatly simplifies your web application by shrinking the middle layer and removing dependencies.

Syntax

Assuming you have a JSON blob like:

{
   subject: "The Hitchhiker's Guide to the Galaxy",
   date: "<i>1978</i>",
   unread: true,
   priority: "urgent",
   bookmarks: {
     url: "www.google.com"
   },
   keywords: [
     {name: "Brilliant"}, {name: "Masterpiece"}, {name: "Witty"}
   ]
 }

Modifying a node's contents

You can set a node's content with the data-qtext attribute and the property name as the parameter.

 <div data-qtext="subject"></div> 
 <input type="text" data-qtext="subject">
 <div>The Hitchhiker's Guide to the Galaxy</div> 
 <input type="text" value="The Hitchhiker's Guide to the Galaxy">
You can also set HTML content into a node with the data-qtext attribute and html as the first parameter.
 <div data-qtext="html date"><i>1978</i></div>

Setting a node's attributes

You can set a node's attribute with the data-qattr attribute. Set the attribute name as the first parameter and the property name as the second parameter.

 <a href="" data-qattr="href bookmarks.url"></a> 
 <input type="checkbox" data-qattr="checked unread"> 
 <input type="button" data-qattr="disabled unread"> 
 <div class="" data-qattr="class priority"></div>
You can set multiple attributes.
<a href="" class="" data-qattr="class priority; href bookmarks.url"></div>

Show or hide a node

You can make a node visible or hidden (style.display = "none") with the data-qif attribute.

<div data-qif="unread">You have unread messages</div> 
 <div data-qif="not:unread">You don't have unread messages</div> 
 <input data-qif="priority eq urgent" type="submit" value="Message is Urgent">
Notice you can use the comparators not, eq, ne, gt, lt, cn, nc for negation, equals, not equals, greater than, less than, contains, and, not contains.

Defining a shortcut

You can define a shortcut with the data-qdef attribute.

<div data-qdef="m forest.trees"> 
   <div data-qtext="m.title"></div> 
   <div data-qtext="m.date"></div> 
 </div>
This attribute cannot be used on the same node with a data-qrepeat attribute, but it can be used on its parent or children.

Repeat a node multiple times

You can repeat a node multiple times based on an array of objects with the data-qrepeat attribute. It works with all HTML elements.

 <html> 
 <table> 
   <tr><th>Opinions</th></tr> 
   <tr data-qrepeat="m keywords"><td data-qtext="m.name"></td></tr> 
 </table> 
 </html>
 <html> 
 <table> 
   <tr><th>Opinions</th></tr> 
   <tr><td>Brilliant</td></tr> 
   <tr><td>Masterpiece</td></tr> 
   <tr><td>Witty</td></tr> 
 </table> 
 </html>
If the array of objects is empty or null, the node will be hidden via style.display = "none", similar in behavior to the data-qif attribute.

Access nested properties

If your data is nested inside multiple properties of the JSON object, you can use the dot notation to reach the nested data.

{ 
     rss: { 
         feeds: { 
             count: "42"
         }
     }
 }
 

<div data-qtext="rss.feeds.count"></div>

To access index 3 of an array named books, do books.3.title.

More Syntax

For more syntax tips, check out the Syntax and FAQ.

Getting Started

  • Distal works best if your server backend returns JSON.
  • Add the Distal script tag in your HTML
    <script src="http://distal.googlecode.com/svn/trunk/distal.js"></script>
  • Design your web application user interface in regular HTML. Add dummy data inside the HTML, so you can pad text out nicely and know what it will look like to the user.
  • Put in TAL attributes inside your HTML based on the structure of your JSON. Use the dot notation to reach nested properties inside the JSON.
  • Depending on your requirements, download the JSON data on page load or when a user clicks on a button. Then call distal(Node, JSON); to apply the JSON to the HTML.

 window.onload = function () { 
     var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 
     xhr.open("GET", "/your/url", true); 
     xhr.onreadystatechange = function () { 
         if (xhr.readyState == 4) distal(document.body, eval("(" + xhr.responseText + ")")); 
     }; 
     xhr.send(null);
 };
  • For performance, you should call distal(Node, JSON) on a more specific node. Like distal(document.getElementById("dialog1"), response).

Use Cases

distal(document.getElementById("scoreboard"), scoreList);
  • Updating Toolbar Buttons based on a document's state:
distal(document.getElementById("toolbar"), {clipboard:true, italic:false, bold:true, underline:false});
  • Updating your Widget's View with data:
distal(this.container, this.getTableModel());

Scope

Distal parses a node tree and feeds it data from a Javascript object. It works on IE6+, Firefox, Chrome, Safari and iOS 4+. You still need to bring your own application logic, data persistence, HTML and event handling. You just need to ensure that you call distal whenever you want to update your interface and pass it a root node and a JSON object.

Distal does not have any dependencies but can also work together with an Ajax library such as jQuery, Dojo, Scriptaculous, Underscore and Backbone. They do not overlap in functionality, but rather Distal introduces a new way to work with your DOM in a loose way. Distal also supports RequireJS and follows ECMAScript 5 Strict mode.

See the wiki page for more articles.

Powered by Google Project Hosting