Someone tried to recreate smarty in js:
// actually from a template file, not hardcoded in the javascript
html = '<span class="{test}">yay</span>';
html = change(html, 'test', 'foo bar');
function change(html, key, value){
html = html.replace('{'+key+'}',value);
html = html.replace('%7B'+key+'%7D',value);
return html;
}
element.innerHTML = html;
In FF this works fine (as expected):
<span class="foo bar">yay</span>
In IE 7/8 and probably 6... it gives me this:
<span class="foo" bar="">yay</span>
Why does it create the extra attribute i开发者_运维百科nstead of doing what I expected it to do?
Someone tried to recreate smarty in js
I really wish they wouldn't do that...!
I suspect what's happened here is that the code is grabbing the original HTML from an element's innerHTML
instead of a string as you write above. In that case, IE will serialise its DOM into what it thinks is a nice way to format HTML markup, which may not be much like the markup it was originally fed. One of the questionable things it may do in this case is to omit quotes:
<SPAN class={test}>yay</SPAN>
“But, that's not valid HTML!”, you complain. Pfft — like IE cares.
Now do the replace and you get:
<SPAN class=foo bar>yay</SPAN>
Where bar
is obviously a new attribute and will be parsed into a separate Attr node when you write it back to the innerHTML
.
Once again, the moral is don't process HTML with regex. Browsers are no more obliged to give you correct HTML when you read innerHTML
than your average inexpert HTML author-clod is.
This code will fail not just for this case but also anything with regex special characters in the key, or replacement-special characters in the value, or HTML special characters anywhere, and doesn't allow the same key twice, and for some unknown reason attempts to template URL-encoded strings (?), potentially messing up if the replacement value contains curly brackets.
If you can keep it all in the DOM, assigning to span.className
is simple and safe. If you must template with HTML strings (and if you do, you need to look at HTML escaping to avoid the gaping XSS holes that plague most JS templating systems), then you'll need to keep the input HTML template as the original text string, not reading it from a DOM.
精彩评论