开发者

jQuery template() for putting a URL into src= attribute of image

i have a jquery template:

<div id="test_template">
    <img src="${url}" width="31" height="32" alt="" />
    ${url}
</div>

I compile it with this:

test_template = $('#test_template').template();

I rende开发者_开发知识库r it with this:

$.tmpl(test_template, {url:'http://sstatic.net/stackoverflow/img/sprites.png'}).appendTo('#render_test');

the end result is this:

<div id="render_test">
<img height="32" width="31" alt="" src="$%7Burl%7D">   http://sstatic.net/stackoverflow/img/sprites.png</div>

obviuosly I expected the URL to be in the src="" tag... but it is not (though it IS being outputted correctly after the tag). if I look at the anonymous function created by template(), I see that it isn't turning the src="${url}" into javascript. it is just encoding it as HTML and spitting it back out

what am I doing wrong?


what am I doing wrong?

Using a real <img>.

When you use attributes like <img src>, the browser may fix up your values to make them valid. So because the characters {} aren't valid in a URL, the browser may encode them to %7B%7D. This is probably browser-specific; Nick's example that he says works fails for me in Firefox. (It also fails in IE due to the missing var on test_template, but that's an unrelated issue.)

Remember when you write HTML elements, the HTML source is not maintained. The browser will parse it into a load of DOM nodes. When you call html() (innerHTML) what you get is a serialisation of those DOM nodes, which does not exactly preserve the formatting of the original markup. Especially when the original markup isn't really valid HTML but just a placeholder for templating.

For this reason I would not use actual in-page elements to template from, and I consider jquery-tmpl's encouragement of this with its $(element).template() method to be a mistake. That's not the only issue I with the plugin. For example if you put data() or an event handler on an element inside the template, that data/handler gets copied accidentally on IE but not other browsers, due to naïve innerHTML copying and jQuery's horrid node-identity hack.

So if you must use jquery-tmpl, use strings with it, not nodes. Use strings embedded in a <script> if you have to, but don't use actual in-page elements. (As well as this problem, it's also semantically questionable to have content in the document that isn't actual content.)


Make sure you're using the latest version of the templates plugin, I have no issues using the latest plugin and either jQuery 1.4.2 or 1.4.3.

You can see the working demo of your code here.


I fix that with an ugly hack that uses TmplItem :

        function fixRenderedTemplate(rendered){
            var fixArray = [["img", "src"], ["a", "href"]];
            for (var i=0; i<fixArray.length; i++){
                var tagName = fixArray[i][0];
                var attrName = fixArray[i][1];
                $(tagName, rendered).each(function(index, elem){
                    var data = $(elem).tmplItem().data;
                    var fixTemplate = unescape($(elem).attr(attrName));
                    var url = $.tmpl(fixTemplate, data).text();
                    $(elem).attr(attrName, url);
                });
            }
            return rendered
        }

Just call the function on your rendered template

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜