1

Our sign-in page for web apps currently uses javascript string concatenation to generate markup:

var signinHtml='<div>'+
    '    <form class="form-signin" method="post">'+
    '        <div class="form-signin-app-icon"></div>'+
    '        <h2 class="form-signin-heading">'+appName+'</h2> '+
    '        <h4 class="form-signin-heading-sub">'+appMotto+'</h4>'+
    '        <div class="form-signin-input">'+
    '            <input id="username" type="text" name="username" class="input-block-level" placeholder="Username"></input>'+
    '        </div>'+
    '        <div class="form-signin-input">'+
    '            <input type="password" name="password" id="password" class="input-block-level" placeholder="Password"></input>'+
    '        </div>'+
    '        <button class="btn btn-small btn-inverse form-signin-button" type="submit" id="signin">Sign in</button>'+
    '    </form>'+
    '</div>';       

    $(self).html(signinHtml);

This approach works but is messy, error-prone, and probably not the best way of doing it. From what I've read, arrays are more efficient performance-wise but even worse in terms of readability. Can anyone recommend a cleaner/better alternative?

4
  • 2
    There are many ones, like having only one string (yes, you can have a multi-line string literal in JS), using jquery DOM functions, using a template, etc. Commented Jul 31, 2014 at 13:55
  • And no arrays aren't more efficient, that's mostly urban legend based on old tests on old versions of some engines. Commented Jul 31, 2014 at 13:57
  • I use document.createElement() to create elements... jQuery has a way to do this as well, but it's slower (obviously) -- ($("<div>") creates a div) Commented Jul 31, 2014 at 14:02
  • Concatenation is one of the things that recent optimizations in many browsers have focused on. Do not worry too much about performance of arrays versus strings; focus on readable code. Commented Jul 31, 2014 at 14:12

4 Answers 4

7

I would suggest looking up template engines, such as Mustache or Handlebars.

Those would allow you to define your markup in a simple language that is then parsed by the template compiler so that they're available in your Javascript, so that all you have to do is pass in your data and get HTML back.

EDIT: An example of how this could work with Handlebars (I'm using that because it's what I used last, but the concepts are the same regardless of what you use).

First you create a template. The template is just your HTML, but you represent your data with tokens. It could look like this:

<div>
    <h1>My name is {{ name }}</h1>
    <p>Here's some information about me: {{ about }}</p>
</div>

That template has to be accessed somehow in your Javascript. The simplest way to do that is to simply put it in a script tag with a certain type:

<script id="my-template" type="text/x-handlebars-template">OUR TEMPLATE GOES HERE</script>

Then we have to compile the template. What that means is that the template engine takes the HTML-like text that we created, parses that and turns it into a javascript function. In handlebars, that is done like this:

var template = Handlebars.compile($('#my-template').html());

(Note that in this example I'm using jQuery to get the contents of the script tag)

template is now a Javascript function that will return HTML if I supply it with the data we need (name and about). So let's do that:

var data = {name: 'Tommy Brunn', about: 'I like cats and Belgian beer'};
var output = template(data);

output will now contain the HTML from our template, but with the tokens replaced with my data:

 <div>
    <h1>My name is Tommy Brunn</h1>
    <p>Here's some information about me: I like cats and Belgian beer</p>
</div>

This is just the simplest example of a template. Some templating languages allow you to do things like loop over lists, modify variables (for example, uppercasing) or perform selections ("if name is more than 5 letters long, reverse it").

In this example, the compilation of the template is done on the client side. That's fine in most cases, but if you need the extra performance, you probably want to do the compilation on the server side. Most (maybe all?) template engines provide you with a way to do that as part of your build process. What you'd end up with then is a Javascript file that contains the function that your template compiled to. Another benefit of that is that you won't need to include the full compiler on your site. You only need a smaller runtime instead.

Sign up to request clarification or add additional context in comments.

6 Comments

when using mustache, does the data need to be in JSON form? Because currently it's just using html fragments and I don't want to have to restructure.
Yes, every Javascript template engine I've ever used expects to receive a single object representing your data.
Ok. Is it possible for you to edit the answer to include how the code above would be rewritten if using mustache, as a basis for comparison? I'm looking at a tutorial right now but it seems rather confusing. Haven't used templates before
Added a basic example now.
Ok thanks so much! This makes sense to me now :) My only question is, you now have the template data stored in a variable called output, correct? How do you actually display it now?
|
2

The best answer to the question has already been provided by Tommy Brunn above, however, there is a solution for if you are dealing with small snippets.

var element = $("<a />", {"href": "http://www.example.com", "target": "_blank", "class": "example-class"}).html("example.com");

parent.append(element);

It is particularly useful if you need to create elements that have a lot of dynamic attributes and require attached events and other interactions. I find it much cleaner than strings of text and then searching (.find()) through them after the fact to find elements.

Comments

1

USE TEMPLATE LITERALS

your code looks like this which use '+' several times and it looks ugly.

var a = 5;
var b = 10;
console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
// "Fifteen is 15 and
// not 20."

How if i write code like this

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."

All the latest browser except Safari , IE supporting template literals

Comments

0

Angularjs also supplies some good template mechanisms, if you're looking for alternatives to those mentioned.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.