Forum Moderators: open
var abbrList = document.getElementsByTagName("abbr");
Then I want to replace each of these with an "acronym" element, keeping any attributes of the abbr, and any nested html. For example, suppose I had the following:
<abbr title="Cascading Style Sheets" class="foo">CSS</abbr>
I want to convert that to:
<acronym title="Cascading Style Sheets" class="foo">CSS</acronym>
Is this possible?
I tried to accomplish it with the DOM by making an acronym, then applying the title and innerHTML from the abbr. The test page below works in Safari and Firefox, but fails in IE. IE neuters the tooltip onmouseover and fails to apply either abbr or acronym styling to the element.
Is there a way to change a tag from one type to another in IE?
<html>
<head>
<script type="text/javascript">
<!--
window.onload = function(){
var theABBR = document.getElementsByTagName('abbr');
var newACRONYM = new Array();
var theABBRparents = new Array();
for (var i=0; i < theABBR.length; ++i)
{
newACRONYM[i] = document.createElement("acronym");
newACRONYM[i].title = theABBR[i].title;
newACRONYM[i].innerHTML = theABBR[i].innerHTML;
theABBRparents[i] = theABBR[i].parentNode;
alert('now you see it...'); //debug
theABBRparents[i].replaceChild(newACRONYM[i],theABBR[i]);
alert('now you don\'t!'); //debug
}
}
//-->
</script>
<style type="text/css">
<!--
abbr { background: red; color: white; }
acronym { background: blue; color: white; }
-->
</style>
</head>
<body>
<p>Welcome to the <abbr title="United States of America">U.S.A.</abbr>!</p>
<p>This is a <acronym title="Default Acronym Example">D.A.E.</acronym></p>
<input type="password" name="vm" id="vmp" value="111">
</body>
</html>
[edited by: DrDoc at 2:31 am (utc) on Feb. 22, 2006]
If anyone has any ideas, I'd love to hear them.
If you are using an XHTML doctype you can simply prefix your <abbr> element with the html namespace.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns:html="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<style type="text/css">
html\:abbr, abbr { background: red; color: white; }
acronym { background: blue; color: white; }
</style>
</head>
<body>
<p>Welcome to the <html:abbr title="United States of America">U.S.A.</html:abbr>!</p>
<p>This is a <acronym title="Default Acronym Example">D.A.E.</acronym></p>
<input type="password" name="vm" id="vmp" value="111" />
</body>
</html>
Tadaa! :)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<!--[if lt IE 7]>
<script type="text/javascript">
window.onload = function() {
var arrAbbr = document.getElementsByTagName('abbr');
for(var i = 0; i < arrAbbr.length; i++) {
var newElem = document.createElement('acronym');
newElem.setAttribute('title', arrAbbr[i].title);
newElem.innerHTML = arrAbbr[i].nextSibling.nodeValue;
var p = arrAbbr[i].parentNode;
arrAbbr[i].parentNode.removeChild(arrAbbr[i].nextSibling);
arrAbbr[i].parentNode.removeChild(arrAbbr[i].nextSibling);
arrAbbr[i].parentNode.replaceChild(newElem, arrAbbr[i]);
}
}
</script>
<![endif]-->
<style type="text/css">
abbr { background: red; color: white; }
acronym { background: blue; color: white; }
</style>
</head>
<body>
<p>Welcome to the <abbr title="United States of America">U.S.A.</abbr>!</p>
<p>This is a <acronym title="Default Acronym Example">D.A.E.</acronym></p>
<input type="password" name="vm" value="111">
</body>
</html>
To explain it a little ... Since IE does not understand the
<abbr> tag at all, document.getElementsByTagName('abbr') only matches the opening tag: To match the closing tag, you would have to do
document.getElementsByTagName('/abbr') ... Quirky, eh?! So, since
document.getElementsByTagName('abbr') only matches the opening tag, we need to treat the contents of the <abbr> element as the sibling of the opening <abbr> tag, and then the closing tag as its own element. Weird, I know. I also threw the whole thing into a conditional comment to only be matched by IE6 and lower.
However, your example only gets the title attribute and not any additional attributes that may be associated with the abbr. I have modified your example to get all of the attributes, and it's included below.
The only problem is that the class attribute is getting ignored, I think because the item started out as an abbr. You can see what I mean in the example below, and you can verify that the class value was indeed copied by uncommenting the alert. But the class value is just ignored. Any ideas if there's a workaround for that?
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<!--[if lt IE 7]>
<script type="text/javascript">
window.onload = function() {
var arrAbbr = document.getElementsByTagName('abbr');
for(var i = 0; i < arrAbbr.length; i++) {
var newElem = document.createElement('acronym');
var abbrAttrs = arrAbbr[i].attributes;
for( var j = 0; j < abbrAttrs.length; j++ )
{
newElem.setAttribute(abbrAttrs[j].nodeName, abbrAttrs[j].nodeValue);
}
newElem.innerHTML = arrAbbr[i].nextSibling.nodeValue;
var p = arrAbbr[i].parentNode;
arrAbbr[i].parentNode.removeChild(arrAbbr[i].nextSibling);
arrAbbr[i].parentNode.removeChild(arrAbbr[i].nextSibling);
arrAbbr[i].parentNode.replaceChild(newElem, arrAbbr[i]);
}
// alert(document.body.innerHTML);
}
</script>
<![endif]-->
<style type="text/css">
.red { color: red; background: #eee; }
</style>
</head>
<body>
<p>Welcome to the <abbr title="United States of America" class="red">U.S.A.</abbr>!</p>
<p>This is a <acronym title="Default Acronym Example" class="red">D.A.E.</acronym></p>
<input type="password" name="vm" value="111">
</body>
</html>
setAttribute does not work for event handlers (such as onmouseover, onclick, onfocus, etc) or the class and style attributes. If the attribute is an event handler, instead of:
elem.setAttribute('onmouseover', 'func()'); elem.onmouseover = func; If the attribute is class, instead of:
elem.setAttribute('class', 'clsname'); elem.className = 'clsname'; If the attribute is style, instead of:
elem.setAttribute('style', 'background: red; color: blue;'); elem.style.background = 'red'; elem.style.color = 'blue'; elem.style.cssText = 'background: red; color: blue;';
[perl]<!--[if lt IE 7]>
<script type="text/javascript">
window.onload = function() {
var arrAbbr = document.getElementsByTagName('abbr');
for(var i = 0; i < arrAbbr.length; i++) {
var newElem = document.createElement('acronym');
var arrAttr = arrAbbr[i].attributes;
for(var j = 0; j < arrAttr.length; j++) {
if(arrAttr[j].value != "" && arrAttr[j].value != "null") {
var a = arrAttr[j].nodeName.toLowerCase();
var v = arrAttr[j].nodeValue;
switch(a) {
case "class":
newElem.className = v;
break;
case "style":
newElem.style.cssText = v;
break;
default:
if(a.match(/^on.+$/)) {
newElem[a] = v;
}
else {
newElem.setAttribute(a, v);
}
break;
}
}
}
newElem.innerHTML = arrAbbr[i].nextSibling.nodeValue;
arrAbbr[i].parentNode.removeChild(arrAbbr[i].nextSibling);
arrAbbr[i].parentNode.removeChild(arrAbbr[i].nextSibling);
arrAbbr[i].parentNode.replaceChild(newElem, arrAbbr[i]);
}
}
</script>
<![endif]-->[/perl]