Quantcast
Channel: Hasen Judy
Viewing all articles
Browse latest Browse all 50

Interesting hack to create html templates in javascript

$
0
0

Edit: various people pointed out that this trick is non-standard and not guaranteed to work across browsers, for instance, Firefox. So take this only as an interesting hack .. don’t use it in production

In a quest to have “reusable” knockout.js components, I asked on the mailing list if anyone has had any experience dealing with the problem of packaging the templates.

To distribute your HTML templates for reusability, they are usually written in html files and are meant to be included in your main html file using some server side technology, so for example if you’re using flask/jinja2 you’d use the include tag: {% include 'ko_widget.html' %}

This obviously is not ideal.

At first, I came up with a solution (that now I see is rather crappy) that revolves around a compiler script that crates a little javascript file that will recreate the template and insert it to the DOM using the document.body.insertAdjacentHTML method.

This is the core of it. Very simple. Takes html content, returns javascript:

def process_content(content):
    js_content = json.dumps(content)
    return "document.body.insertAdjacentHTML('beforeend', {0})".format(js_content)

But then someone showed me a different approach: a magic way to include html snippets in javascript. Actually it’s a hack to create multiline strings.

https://github.com/xdenser/kc-tree-habr/blob/master/tree.js#L106

It’s amazing what this can do:

function hereDoc(f) {
  return f.toString().
      replace(/^[^\/]+\/\*!?/, '').
      replace(/\*\/[^\/]+$/, '');
}

This function will extract the text content of block comments inside a function definition and return it as a string!

So like ….. you can create a multiline string like this:

var mlstring = hereDoc(function() {
    /*
        This is a multiline string ..
        Really .. it is!

        it also contains html:

            <a href="http://google.com">Google</a>
    */
    })

Printing the content of mlstring in the Chrome console:

&gt; mlstring
"
            This is a multiline string ..
            Really .. it is!

            it also contains html:

                <a href="http://google.com">Google</a>
        "

Building on this

I created a function that takes a multiline string in this way and then wraps it in a script tag (with type set to text/tempalte), then sets a unique (random) id to this tag, then inserts it to the dom (or if the dom is not ready, waits for the dom to get ready then does the insertion) and return the generated id.

/**
    Takes a namespace and a function who's inside is a comment containing the content of an html template.

    Generates a randomized id (based on the name space, i.e 'template..random.digits'

    Returns the id

    Guarantees the templates gets inserted into the dom: either now or when it's ready (if the page is still loading).
 */
insertTemplate = function(namespace, f) {
    if(!namespace) { namespace = 'generic'; }
    var text = hereDoc(f);
    var random = (Math.random() * 9000).toFixed(0);
    var timestamp = (new Date()).getTime();
    var id = "template." + namespace + "." + random + "." + timestamp;

    var node = document.createElement("script");
    node.setAttribute("id", id);
    node.setAttribute("type", "text/template");
    node.innerHTML = text;

    var insertNode = function() {
        console.log("Inserting template");
        document.body.appendChild(node);
    }

    // insert node now or when body is loaded
    if(document.readyState == "loading") {
        document.onreadystatechange = function () {
            if (document.readyState == "interactive") {
                insertNode();
            }
        }
    } else {
        insertNode();
    }

    return id;
}

If only this were standard compliant, it would make it possible to include html templates inside javascript files & make it easier to package and distributes knockout.js components.


Viewing all articles
Browse latest Browse all 50

Trending Articles