Cobblestone

Syntax

The entirety of its syntax is represented in this example:

<p>Hi, my name is {name}.</p>

{if traveled}
    <p>Here are the places I have been:</p>
    <ul>
    {each travels as t}
        <li class={t.classes}>
            In {t.year} I went to {t.place}.
        </li>
    {/each}
    </ul>
{elif interested}
    <p>I've never been anywhere, but I would like to travel some time.</p>
{else}
    <p>I'm more of a stay-at-home kind of person.</p>
{/if}

At first blush, it seems to have everything you need:

  1. Interpolation. Any variable inside braces, like {var}, will be replaced with its value, automatically escaped for HTML.
  2. Branching, with if, elif, and else
  3. Looping, with each

Interactivity

Changes to any variable will automatically rerender the pieces that depend upon it. The recommended way to change a variable is with old-fashioned, event-handler attributes, written in line with the element itself.

<p><label>Name: <input value="{name}" oninput="name = this.value"></label></p>
<p>Hi, my name is {name}.</p>

It works like this. Feel free to try changing the name.

Set-up

  1. Include this library, anywhere on the page.
  2. Put your template in another <script> tag, whose type is text/x-cob.
  3. Set an attribute on the template called data-key, equal to the name of a global variable that holds the data.

For example:

<!doctype html>
<html>
    <head>
        <title>Example</title>
    </head>
    <body>
        <script>
            var context = { name: 'Bob' };
        </script>
        <script type="text/x-cob" data-key="context">
            <p>Hi, my name is {name}.</p>
        </script>
        <script src="cobblestone.js"></script>
    </body>
</html>

On page load, the library will take the current value of the data and render the template wherever you have it on the page (technically, it will put it right after it, but script tags take up no space).

Note

If your data isn't ready on page load, then don't put the data-key attribute yet on the <script> tag. In fact, this will likely be the case most of the time, since most people will be fetching their data with AJAX. In that case, wait until after you assign the data to the global variable. Then programmatically set the data-key on the script tag:

template.dataset.key = 'x';

If the data-key was set but the data object incomplete (that is, it didn't have all of the properties used by the template), then the library would bomb out as it tried to fill it out. However, if it's just a script tag with type="text/x-cob", and no data-key, then the library will put a watch on the tag (specifically, a MutationObserver). Any time the attribute is set or changes, it will rerun the template. (Actually, it watches for changes to the attribute regardless, even if it is set to something valid on page load.)