PDA

View Full Version : Empty elements not created correctly by DomHelper.createHtml



zkim
4 Nov 2006, 9:53 PM
Jack,
Found a small bug when I was using the DH to create input elements. As it stands, the DH is appending a close tag to 'empty' elements like input, img, br, hr, etc which, (surprise surprise), breaks IE:



var input = YAHOO.ext.DomHelper.append(this.container,
{
tag: 'input',
type: 'text',
style: 'width: 90%',
value: 'some value'
});



produces:



<input type="text" style="width: 90%" value="some value"></input>



Again, works fine in FF, but not IE.

Code to follow...

zkim
4 Nov 2006, 9:58 PM
Here's the possible fix:

From: DomHelper.js



// build as innerHTML where available
/** @ignore */
function createHtml(o){
var b = '';
b += '<' + o.tag;
for(var attr in o){
if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue;
if(attr == 'style'){
var s = o['style'];
if(typeof s == 'function'){
s = s.call();
}
if(typeof s == 'string'){
b += ' style="' + s + '"';
}else if(typeof s == 'object'){
b += ' style="';
for(var key in s){
if(typeof s[key] != 'function'){
b += key + ':' + s[key] + ';';
}
}
b += '"';
}
}else{
if(attr == 'cls'){
b += ' class="' + o['cls'] + '"';
}else if(attr == 'htmlFor'){
b += ' for="' + o['htmlFor'] + '"';
}else{
b += ' ' + attr + '="' + o[attr] + '"';
}
}
}

*** if(this._isEmptyElement(o.tag))
*** b += ' />';
*** else
b += '>';
if(o.children){
for(var i = 0, len = o.children.length; i < len; i++) {
b += createHtml(o.children[i], b);
}
}
if(o.html){
b += o.html;
}

*** if(!this._isEmptyElement(o.tag))
b += '</' + o.tag + '>';

return b;
}

//List of empty elements from http://www.cs.tut.fi/~jkorpela/html/empty.html#html
function _isEmptyElement(sTag) {
switch(sTag) {
case 'base':
case 'basefont':
case 'br':
case 'frame':
case 'hr':
case 'img':
case 'input':
case 'isindex':
case 'link':
case 'meta':
case 'nextid':
case 'range':
case 'spacer':
case 'wbr':
case 'audioscope':
case 'area':
case 'param':
case 'keygen':
case 'col':
case 'limittext':
case 'spot':
case 'tab':
case 'over':
case 'right':
case 'left':
case 'choose':
case 'atop':
case 'of':
return true;
default:
return false;
}
}

(***'s are changes in code)


Hope this helps, and thanks again for your hard work.

jack.slocum
5 Nov 2006, 3:29 AM
I'm surprised that breaks, even in IE. I have used it with input tags without any problems. Either way though, it's still invalid markup so it should be fixed.

I did it a little different but the same concept:

Shared RE defined in top of Domhelper:
var emptyTags = /^(?:base|basefont|br|frame|hr|img|input|isindex|link|meta|nextid|range|spacer|wbr|audioscope|area|param|keygen|col|limittext|spot|tab|over|right|left|choose|atop|of)$/i;

And then in createHtml:


if(emptyTags.test(o.tag)){
b += ' />';
}else{
b += '>';
if(o.children){
for(var i = 0, len = o.children.length; i < len; i++) {
b += createHtml(o.children[i], b);
}
}
if(o.html){
b += o.html;
}
b += '</' + o.tag + '>';
}