Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm doing my first major jQuery development. It's a Widget for recurring events, and is as such a fairly complex beast. The full code is available at https://github.com/collective/jquery.recurrenceinput.js for those who want to check it out. I appreciate any kind of feedback about any part of the code, so anyone who wants to take a look at it, that would be awesome.

I have a couple of specific questions, and it seems best to put them as separate posts, and here is the second one:

I have several big snippets of HTML and I'm using jQuery templating for this. My question is on the best way to include these templates. Currently I'm using two different ways, and none of them are obviously better than any other.

In one case I use a string literal:

var OCCURRENCE_TMPL = ['<div class="recurrenceinput_occurrences"><hr/>',
    '{{each occurrences}}',
        '<div class="occurrence>',
            '<span class="date ${occurrences[$index].type}">',
                '${occurrences[$index].formatted_date}',
            '</span>',
            '<span class="action">',
                '{{if occurrences[$index].type === "rrule"}}',
                    '<a date="${occurrences[$index].date}" href="#"',
                       'class="${occurrences[$index].type}" >',
                        'Exclude',
                    '</a>',
                '{{/if}}',
                '{{if occurrences[$index].type === "rdate"}}',
                    '<a date="${occurrences[$index].date}" href="#"',
                       'class="${occurrences[$index].type}" >',
                        'Remove',
                    '</a>',
                '{{/if}}',
                '{{if occurrences[$index].type === "exdate"}}',
                    '<a date="${occurrences[$index].date}" href="#"',
                       'class="${occurrences[$index].type}" >',
                        'Include',
                    '</a>',
                '{{/if}}',
            '</span>',
        '</div>',
    '{{/each}}',
    '<div class="batching">',
        '{{each batch.batches}}',
            '{{if $index === batch.current_batch}}<span class="current">{{/if}}',
                '<a href="#" start="${batch.batches[$index][0]}">[${batch.batches[$index][0]} - ${batch.batches[$index][1]}]</a>',
            '{{if $index === batch.current_batch}}</span>{{/if}}',
        '{{/each}}',
    '</div></div>'].join('\n');

$.template('occurrence_tmpl', OCCURRENCE_TMPL);

OK, so strictly it's an array of string literals, but that's to make JSLint happy. I then use this:

result = $.tmpl('occurrence_tmpl', data);
occurrence_div = form.find('.recurrenceinput_occurrences');
occurrence_div.replaceWith(result);

This is neat and simple, but the result is a lot of HTML inline. One of the templates is 219 lines long... :-)

The other technique I use is to include the template as if it is a script in the HTML:

<script id="jquery-recurrenceinput-form-tmpl" type="text/x-jquery-tmpl" src="../src/jquery.recurrenceinput.form.js" ></script>

And I load that HTML via ajax, stick it in a variable and make a template of it:

    if ($.template.recurrenceinput_form === undefined) {
        $.ajax({
            url: $(conf.template.form)[0].src,
            async: false,
            success: function (data) {
                conf.template.form = data;
            },
            error: function (request, status, error) {
                alert(error.message + ": " + error.filename);
            }
        });
        $(conf.template.form).template('recurrenceinput_form');
    }

And I can then use that:

form = $.tmpl('recurrenceinput_form', conf);
overlay_conf = $.extend(conf.form_overlay, {});
form.overlay().hide();

This means I don't have the template inline, which is good, but it also means using the Widget is a bit more involved as you need the tag in the HTML, which is bad, and it is a bit of a horrid hack.

Opinions on this is welcome, and even more welcome would be a third way that doesn't suck. :-)

share|improve this question

3 Answers 3

up vote 2 down vote accepted

I think loading the templates via AJAX is an elegant solution.

The idea of using a <script>-tag with a non-standard type is also applied in this example from the YUI 3 documentation. Your idea to use AJAX to load it is, in my opinion, a much cleaner solution to this dirty problem.

share|improve this answer
    
It does result in warnings on mismatches of file types on some browsers, so in the end I decided on merging the templates into the main JS file. Those warning probably can be avoided with some fiddling of the web-server config, though. –  Lennart Regebro Dec 28 '11 at 18:21

You might want to consider using a toolkit geared towards this sort of thing so you don't have to re-do it yourself. With Dojo it's really easy to create custom widgets, they cache the html, etc (using templates). I heard JQuery was going to implement the AMD define/require standard so you could probably mix the toolkits if you wanted to without too much hassle. If not though it'd be worth looking at how they did it.

share|improve this answer

I agree, the string literal in JS is unwieldy. And requesting the HTML via Ajax is more than you need.

The simplest thing is to insert the template on the page as HTML. Can you include the template on your page, not as Javascript, but as HTML? As in,

<div style="display: none">
  <div class="recurrenceinput_occurrences"><hr/>
    {{each occurrences}}
     <div class="occurrence>
        <span class="date ${occurrences[$index].type}">
     ...
</div>

You can either use this as a template, and insert the results of the evaluation into the DOM elsewhere. Or, in some cases, insert it back where it was on the page (and don't use the display: none).

share|improve this answer
    
No, I can't ask everybody that uses this widget to paste in several hundred lines of HTML split into three templates into their webpages. –  Lennart Regebro Oct 29 '11 at 5:22
2  
Yeah, now that I see it's a plugin, I think your only nice option (for your users) is embed it into your plugin JS code. You might want to spike on different ways to embed it. You can include it as a template (as you have done). You might look at what it would take to build the mark up-- or portions of it-- programmatically. Often this can be smaller and easier to test. –  ndp Oct 31 '11 at 2:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.