Forum Moderators: open

Message Too Old, No Replies

Can I change an element name with JavaScript?

Want to change an abbr to an acronym

         

Fotiman

5:30 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I want to find all <abbr> elements on a page:

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?

whoisgregg

12:28 am on Feb 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Spliced from [webmasterworld.com...]

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]

Fotiman

2:51 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You are correct, that is what I'm trying to do (replace abbr with acronym). However, I don't need to do this for any browser EXCEPT IE 6 and lower (other browsers support abbr, and IE 7 is supposed to as well), so I was using conditional comments to ensure only IE 6 and lower would try to do the replacement.

If anyone has any ideas, I'd love to hear them.

DrDoc

6:33 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There's a simpler fix.

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! :)

Fotiman

6:49 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm not using XHTML.
Got anything else? :)

DrDoc

10:08 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Working on it.

getElementsByTagName does not work, as IE only captures the opening tag.

DrDoc

10:30 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ok, here we go :)

<!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:
<abbr title="United States of America">U.S.A.</abbr>

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.

Fotiman

11:22 pm on Feb 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Very nice. That's what I was stuck on (that it was only getting the opening tag).

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>

DrDoc

12:10 am on Feb 22, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In IE,
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()');

do this instead:
elem.onmouseover = func;

If the attribute is class, instead of:

elem.setAttribute('class', 'clsname');

do this instead:
elem.className = 'clsname';

If the attribute is style, instead of:

elem.setAttribute('style', 'background: red; color: blue;');

do this instead:
elem.style.background = 'red';

elem.style.color = 'blue';

or:
elem.style.cssText = 'background: red; color: blue;';

DrDoc

3:12 am on Feb 22, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So, what you most likely want to do is:

[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]

DrDoc

3:18 am on Feb 22, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



By the way, for those who stumble upon this thread ... Don't use <abbr> for acronyms, or <acronym> for abbreviations.

Acronyms:
radar
scuba
FYI
WYSIWYG

Abbreviations:
incl
excl
max
min