1

I'm trying to replace multiple words with new words, each time I'm rendering an HTML template.

Instead of having to loop through the template (which is quite big) three times to look for three different words, I'd like to combine the three words and their replacements, and only loop through the template once. (Also, obviously below code only replaces the last word, {id} since it overrides the other two replacement attempts above it).

       $.get('/templates/list-item.html', function(data) {
          var template = data,
              tmp = '';

          $.getJSON('conf.json', function(data) {
            var items = [],
                list = data.default;

            for (var item in list) {
              var name = item.name,
                  value = list[item].value,
                  id = list[item].id;

              tmp = template.replace('{name}', name);
              tmp = template.replace('{value}', value);
              tmp = template.replace('{id}', id);

              items.push(tmp);
            }

            $('<div/>', {
              html: items.join('')
            }).appendTo('body');
          });
        });

Obviously rendering templates shouldn't be done with JS, but since it's for internal use only, no backend is available and it doesn't need to be indexed by Google, it's fine for the time being.

patad
  • 9,364
  • 11
  • 38
  • 44

1 Answers1

9

You can use a callback function to replace template variables. Consider for example:

template = "{foo} and {bar}"
data = {foo:123, bar:456}

template.replace(/{(\w+)}/g, function($0, $1) {
    return data[$1];
});

I'd also suggest replacing the loop with map():

items = $.map(list, function(item) {
   var data = {name: item.name, value:.... etc }
   return template.replace(/{(\w+)}/g, function($0, $1) {
       return data[$1];
   });
}

/{(\w+)}/g basically means the following:

/                - start pattern
{                - match { literally
    (            - begin group 1
        \w       - a "word" character (letter+digit+underscore)
        +        - repeat once or more
    )            - end group 1
}                - match } literally
/                - end pattern
g                - match globally, i.e. all occurences

When the callback function is called, it gets the whole match as its first parameter and the value of the group 1 as the second. So when it sees {foobar}, it calls callback("{foobar}", "foobar").

georg
  • 211,518
  • 52
  • 313
  • 390
  • Fantastic! Would you mind explaining what (/{(\w+)}/g actually does? Huge thanks! – patad May 30 '12 at 06:48
  • What are the benefits of using $.map()? Is it faster than for in loop, or just easier to read? – patad May 30 '12 at 06:49
  • `/{(\w+)}/` is a [regular expression](http://www.javascriptkit.com/javatutors/re.shtml). `map` is easier to read and prevents [loop closures](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) troubles. – georg May 30 '12 at 07:00
  • I understand that /{(\w+)}/ is a regexp. I am just curious to know what it exactly does. It's not obvious if you are not familiar with regexps like me. – patad May 30 '12 at 07:05
  • 1
    @pata: I added some explanations to the post. – georg May 30 '12 at 07:11