kganser.com

jsml available for jQuery

Jsml (javascript markup language) is a concise way of generating pieces of the DOM dynamically. If you've ever tried to build up a chunk of the DOM using the browser's DOM API, you know that the resulting code is repetitive and hard to read:

var div = document.createElement('div');
div.appendChild(document.createTextNode("Don't click "));
var a = document.createElement('a');
a.href = 'http://kganser.com';
a.onclick = function(e) { e.preventDefault(); alert('You Clicked!'); };
a.appendChild(document.createTextNode('here'));
div.appendChild(a);
document.body.appendChild(div);

The same structure can be generated using jsml as follows:

$(document.body).jsml({div: [
  "Don't click ",
  {a: {
    href: 'http://kganser.com',
    onclick: function(e) { e.preventDefault(); alert('You Clicked!'); },
    children: 'here'
  }}
]});

Production rules

node = object
     | nonobject
object = {tagname: nonobject}
       | {tagname: {property, ...}}
property = attribute: value
         | children: node
nonobject = [node, ...]
          | function
          | string
          | number

An element object is specified with a single key and value. The key is the element's tagname, and its value is either a nonobject specifying its contents or an object with its recursively addressable attributes, where key "children" specifies any contents. Other data types specified for node are ignored.

Examples

jsml html
{div: null}
<div></div>
{div: 'hello'}
<div>hello</div>
{div: {
style: {backgroundColor: 'red'},
children: 'world'
}}
<div style="background-color: red">world</div>
{ul: {
className: 'list',
children: [
{li: 'hello'},
{li: 'world'}
]
}}
<ul class="list">
<li>hello</li>
<li>world</li>
</ul>
{div: function(elem) {
elem.innerHTML = 'hello, world';
}}
<div>hello, world</div>

Leveraging Javascript

The last example uses a function to populate the parent element, which is passed in by the jsml renderer as it traverses the structure. The function can also synchronously return a jsml structure on which the renderer will continue to operate. This allows you to intercept pointers to the elements as they are generated, which is particularly useful for asynchronous operations:

$(document.body).jsml({div: function(elem) {
  setTimeout(function() {
    elem.innerHTML = 'done!';
  }, 1000);
  return 'loading...';
}});

This is just one example of the benefits of leveraging pure javascript and its runtime environment (i.e., the event loop, closures, and lexical scoping) to generate both the markup and functionality of an application. Numerous frameworks (including those intended to run client-side) seek to separate logic from data in application development, creating templating languages with ungainly, ad-hoc syntaxes that re-implement the simplest features of a programming language. The result is slower, more complex and bloated applications with more global variables and an added learning curve. Rather than separate the two or try to insert logic into DOM markup, jsml represents DOM data naturally as a subset of the programming language, allowing entire applications to be written as a single javascript expression.