Larry Steinle

April 17, 2014

Create HTML Using CSS-Shorthand

Filed under: Web — Larry Steinle @ 8:56 pm
Tags: , , , , , , , ,

Creating HTML markup requires a lot of typing. For nearly every opening tag there is a closing tag. There is a shorter, faster way to create HTML!

The Idea

Shorthand is a style of writing that permits the writer to document a thought more quickly with less effort. Shorthand logic also exists in programming. A perfect example of programmatic shorthand can be found in Regular Expressions. Regular Expressions provide an incredible amount of flexibility when a developer needs to find a character pattern match in text. While Regular Expressions can be somewhat cryptic they are very efficient and generally cleaner than procedural code written for the same complex, text matching pattern.

With these concepts in mind I began to wonder if we could create a type of HTML shorthand to more easily and quickly generate HTML tags? Before endeavoring on this idea I performed a few Google searches and found the Emmet code project on GitHub. This code base was very close to what I had in mind and based upon the examples was an excellent proof of the shorthand idea I was considering.

If you are looking for a plug-in for your editor to more quickly create HTML tags then I strongly recommend the editor plug-ins at the official Emmet Web Site.

What I needed was a means to dynamically generate lots of HTML quickly and easily. Frameworks like jQuery, Knockout, Backbone and Angular use HTML fragments with specific configuration rules to dynamically generate HTML. The JSON object is bound to the template. Beneficial but not quite what I had in mind for my most recent project.

What I wanted was a means to send a concise set of instructions defining how to convert the JSON object into a DOM object. CSS shorthand provided the perfect solution. Highly flexible and much smaller than the traditional template approach utilized by standard frameworks, CSS shorthand could easily transform JSON in a reliable, predictable manner. It only took a few days to create the code base that would allow me to convert JavaScript objects to HTML Document Object Model (DOM) objects using Cascading Style Sheet (CSS) selector shorthand and a few custom commands.

The Premise

CSS allows developers to set the styling for HTML tags. CSS supports referencing tags using the tag name (table, div, p, b, font, etc.), a class name (.className) or a tag id (#tagId). These DOM lookup mediums are called selectors.

body {background-color:red;}
.note {background-color:yellow;}

jQuery popularized the use of CSS selectors to find DOM elements and manage them. If we can use CSS selectors to find DOM elements then why not use them to create the elements in the first place?

How It Works

I created a prototype method called, “renderAsHTML,” on the Object class. This permits any object in JavaScript to be converted into HTML using CSS-like expressions. The renderAsHTML method takes two arguments: the formatter expression and an optional tag into which to inject the HTML. If a target tag is not provided the document body is the default target.

Let’s begin with a simple “hello, world” sample.

The idea is that we can convert any object, even a string, to an HTML DOM element. In this example we convert the string, “Hello, World,” into DOM text placed inside a bold tag.

The JavaScript statement: “Hello, World”.renderAsHTML(“b>{toString}”);
Creates the HTML: <b>Hello, World</b>
Which shows in the browser as: Hello, World

The b indicates that we want to create a bold tag element. The greater than sign (>) indicates that we want the following instructions to be placed as children inside the bold tag. The opening and closing “mustache” brackets identify that we want to display the results of the property or function inside the bold tag. A string object has a toString method that simply returns the string value.

You can view the code for the renderAsHTML method along with samples showing how to use the method in the CSS-Shorthand JSON Transformer fiddle. In the following sections I describe how the format argument in the renderAsHTML method works.

CSS Selectors

Tag Names
Creating tags is very easy. Simply type the name of the tag to create. You can also use the class and id selectors to add a class name or tag id. I have added support for the ampersand to assign a name to the tag.

Shorthand Generated HTML
b <b></b>
div <div></div>
b#important <b id=”important”></b>
b.very <b class=”very”></b>
b@nice <b name=”nice”></b>
b.very#important@nice <b class=”very” id=”important” name=”nice”></b>

Multiple Tag Names

Multiple tag names assigned to the same parent tag can be created by using the sibling operator (+). Alternatively you can use opening and closing parens to denote the same sibling relationships.

Shorthand Generated HTML
b+div <b></b><div></div>
b.important+div#cool <b class=”important”></b><div id=”cool”></div>
(b.important)(div#cool) <b class=”important”></b><div id=”cool”></div>
(b.important)+(div#cool) <b class=”important”></b><div id=”cool”></div>

Nested Tag Names

Use the greater than sign to create child tags.

Shorthand Generated HTML
div#cool>b.important <div id=”cool”><b class=”important”></b></div>

Grouping Tags

Grouping tags help clarify complex relationships. Grouping tags can be used to denote what chains of nodes should be treated as a collective providing more advanced formatting options.

Tables are a good example where grouping is required.

Shorthand Generated HTML
table>(thead>tr>th)+(tbody>tr>td) <table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table>

Actually the sibling operator (+) is optional as the groupings also indicate sibling behavior.

Data Binding

Instead of binding JavaScript objects to HTML DOM tags, the renderAsHTML method transforms JavaScript into DOM using CSS shorthand notation.

To demonstrate the flexibilty of CSS expressions to build HTML we will use the employees JSON objects in the remaining examples:

var employees = [
    {id: 1, name: "John"},
    {id: 2, name: "Jim", specialties: ['Does Stuff', 'Lots of Stuff', 'Sometimes Neat Stuff']},
    {id: 3, name: "Jane"},
    {id: 4, name: "Jerry"},
    {id: 5, name: "Jake"},
    {id: 6, name: "James"},
    {id: 7, name: "Jimbo"}
];

The following examples will only work after you get the source code from the CSS-Shorthand JSON Transformer fiddle.

Commands
The renderAsHTML method uses commands to perform all actions. Each CSS-selector is converted into a command. The command pattern offers a clean, extensible way to provide additional transformation options.

Command Syntax
$commandName(shorthand)
$commandName:commandContext(shorthand)

Where

commandContext is only supported by the block command at this time.
shortHand is optional CSS-shorthand for additional processing.
commandName is one of the following case-sensitive values:
(secondary examples show the recommended shorthand style)

Command Name Description Example Result
addTag Adds the specified tag to the current DOM node. $addTag(div)
div
<div></div>
addAttributes Adds attributes to the current DOM node. div$addAttributes([data-test=’example’])
div[data-test=’example’]
<div data-test=”example”></div>
addClassName Adds the class name to the current DOM node. div$addClassName(example)
div.example
<div class=”example”></div>
addIdName Sets the id name for the current DOM node. div$addIdName(example)
div#example
<div id=”example”></div>
addName Sets the name for the current DOM node. div$addName(example)
div@example
<div name=”example”></div>
value Sets the value for the current DOM node. Use with input tags. input$value(example) <input value=”example”/>
text Appends the provided value to the current DOM node as text. div$text(example) <div>example</div>
html Appends the provided value to the current DOM node as HTML. div$html(‘<b>example</b>’) <div><b>example</b></div>
item Iterates each instance of the current JavaScript context. employees.renderAsHTML(“ul>$item(li>{name})”) <ul>
<li>John</li>
<li>Jim</li>
<li>Jane</li>
<li>Jerry</li>
<li>Jake</li>
<li>James</li>
<li>Jimbo</li>
</ul>
context Sets the JavaScript binding context to the selected object.
Generally used to drill into child objects.
This is one of the few commands that only works in shorthand.
employees.renderAsHTML(“ul>$item(li>{name}+{specialties}:(ul>$item(li>{toString})))”) <ul>
<li>John</li>
<li>Jim
<ul>
<li>Does Stuff</li>
<li>Lots of Stuff</li>
<li>Sometimes Neat Stuff</li>
</ul>
</li>
<li>Jane</li>
<li>Jerry</li>
<li>Jake</li>
<li>James</li>
<li>Jimbo</li>
</ul>
block Defines a section of the shorthand for look-up. The command context argument is required to provide a name. Used with the repeat command for recursive binding. Refer to the CSS-Shorthand JSON Transformer fiddle for an example.
repeat Executes the specified block when the same HTML code structure needs to be generated recursively. Refer to the CSS-Shorthand JSON Transformer fiddle for an example.
root Provides access to the root object.
parent Provides access to the parent object when available.
first Provides access to the first object in the list. If the object is not in a list returns the object. Refer to the CSS-Shorthand JSON Transformer fiddle for an example.
next Returns the next object in the list. The context command may be used to advance more than one position. $next_2({name}) Should advance two positions from the current position and then print the name.
prev Returns the previous object in the list. The context command may be used to retreat more than one position. $prev_2({name}) Should retreat two positions from the current position and then print the name.
last Returns the last object in the list. If the context object is not a list returns the object.

Summary

As the CSS-Shorthand JSON Transformer fiddle demonstrates, using CSS shorthand to create HTML is a promising idea. I hope that I have at least captured your interest and opened the door for new ways of solving old problems.

Advertisement

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: