The textContent and innerText Properties

18 04 2006

In my original post, Using the innerText Property in Firefox, I wrote my example using document.all to determine when to use innerText or textContent.

Because the main purpose of that post was to explain to the reader that Firefox does not support the innerText property but the textContent property, I failed to consider other browsers… yes, shame on me! (thanks Paul for bringing this to my attention).

You see, there are browsers that although don’t support document.all, they DO support the innerText property: Safari and Konqueror.

So, it is more efficient to check if the innerText property is supported by the user agent (thanks, Matthias). The way I do it is like this:

var hasInnerText =
(document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;
var elem = document.getElementById('id');
var elem2 = document.getElementById ('id2');

if(!hasInnerText){
    elem.textContent = value;
    elem2.textContent = value;
} else{
    elem.innerText = value;
    elem2.innerText = value;
}

Why am I using document.getElementsByTagName("body")[0]? Well, because, as you know, document.getElementsByTagName returns an array of elements with that tag name, and since there’s only ONE body tag, I’m calling the first and only index of that array at once. This is so, as you can see in the example above, if you have more than one element that you need to assign a value to.

I have an example. If you wish, check the source out to see how it works.

Compatibility:

  • Linux:
    • Konqueror 3.5.2
    • Firefox 1.5.0.1
  • Mac X:
    • Safari 2.0.3
    • Camino 1.0
  • Windows:
    • Firefox 1.5.0.2
    • Opera 8.54
    • Internet Explorer 6
    • Internet Explorer 7.0.5346.5 Beta 2

Remember, this is one way to do it. Cheers! ;)


Actions

Informations

26 responses to “The textContent and innerText Properties”

27 07 2006
Joe (05:27:41) :

wicked !

thanks a lot

27 07 2006
Juan Wong (08:26:47) :

glad I can help ;)

31 07 2006
Adam Ziegler (16:30:45) :

Thanks! I changed it for function use:

function changeTextById(elementId,changeVal){
    var hasInnerText =
    (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;

    var elem = document.getElementById(elementId);

    if(!hasInnerText){
	elem.textContent = changeVal;
    }else{
	elem.innerText = changeVal;
    }

}
31 07 2006
Juan Wong (17:28:18) :

@Adam:

Thank you for your contribution! Just one little suggestion: What if we leave the innerText support checking outside the function? That way, the variable ‘hasInnerText’ will be a global one. Also, checking the innerText support will be done once and not everytime the function is called. So, a slight modified version of your function would be:

var hasInnerText =
(document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;

function changeTextById(elementId,changeVal){
    if(!hasInnerText){
        elem.textContent = changeVal;
    }else{
        elem.innerText = changeVal;
    }
}

That’s it.

Once again, thanks for your contribution! :D

30 08 2006
Beni Rose (21:42:29) :

Hey, thanks a lot, this post helped a whole load! Now if only I could figure out how to determine the width of a span tag when I haven’t assigned it one in css (it’s “fill out width” if you will) in IE, because apparently in every other browser it’s offset width. Oh well!

P.S. Love the naruto pic

19 12 2006
Ken Odoki-Olam (04:23:49) :

What’s wrong with document.body?

19 12 2006
Juan Wong (06:05:24) :

@Ken,

It hasn’t been feelin’ well lately…

16 01 2007
Jesse Perrin (19:14:49) :

forgot the local var elem above…

var hasInnerText =
(document.getElementsByTagName(”body”)[0].innerText != undefined) ? true : false;

function changeTextById(elementId,changeVal){
    var elem = document.getElementById(elementId);

    if(!hasInnerText){
        elem.textContent = changeVal;
    }else{
        elem.innerText = changeVal;
    }
}

there we go. ;)
Great function! Thanks.

16 01 2007
Juan Wong (19:42:59) :

@Jesse,

Thanks much for catching that! **thumbs up** :)

18 01 2007
Jesse Perrin (04:07:28) :

Going further, I’d suggest the following changes:

1. Put the check for the innerText feature in a function

2. Change the elementId argument for changeTextById to just elem. This way you can also call the function from inside an iframe, for example. I think it makes the function more reusable.

3. Put the initialization of the hasInnerText global variable in a function and call the function from body onload. This ensures proper order.

4. Signify hasInnerText is a global variable somehow, such as using the g_ convention, making it g_hasInnerText

var g_hasInnerText = false;

function checkForInnerTextFeature()
{
    return (document.getElementsByTagName(”body”)[0].innerText != undefined) ? true : false;
}

function initialize()
{
    g_hasInnerText = checkForInnerTextFeature();
}

function changeText(elem,changeVal){
    if(!g_hasInnerText){
        elem.textContent = changeVal;
    }else{
        elem.innerText = changeVal;
    }
}

usage:

var elem = document.getElementById(elementId);
changeTextById(elem, "new text");

or…

var elem = parent.document.getElementById(elementId);
changeTextById(elem, "new text");

(Juan, if this is too far beyond the scope of this article, feel free to snip it out. These things just seem to be helpful, especially the part about proper order. That’s really what screwed me up. If you do, I’d suggest at least mentioning something about the proper order- when and where to do the one-time check for innerText/textContent support.)

hth,
Jesse

18 01 2007
Juan Wong (10:48:57) :

Jesse,

Excellent contribution! The code I post in my articles is simple. It’s just so that readers can have something to start with and take it from there, and that’s what you exactly did.

At a glance, I don’t really think you need the initialize() function. As soon as I get home, I’ll take a better look at this and if I have any suggestions, I’ll let you know.

Once again, your contribution is very much appreciated. **thumbs up**

18 01 2007
Jesse Perrin (14:27:11) :

Does innerHTML work on all the most significant browsers? (I guess this is relative, but…)

If so, then, for an all-in-one function, I’d propose to add an htmlFlag to the ChangeText function in the case you do want to render html:

function ChangeText(elem, changeVal, htmlFlag)
{
	if(htmlFlag)
	{
		elem.innerHTML = changeVal;
	}
	else
	{
		if(!g_innerTextFeatureEnabledFlag)
		{
			elem.textContent = changeVal;
		}
		else
		{
			elem.innerText = changeVal;
		}
	}
}

If innerHTML does not have broad enough support, what would be a good alternative?

18 01 2007
Jesse Perrin (14:34:48) :

argh. I accidentally capitalized the function. my bad. It should be called changeText.

Anyway, so the usage for the above version of changeText would be:

var elem = document.getElementById(elementId);
changeText(elem, "html text", true);

or…

changeText(elem, "non-html text", false);
18 01 2007
Juan Wong (20:18:55) :

Jesse,

I tested your code and it didn’t work for me. The g_hasInnerText never got set to either true or false by the checkForInnerTextFeature() function, and because of that, its original value, when the variable was decleared and initialized, never changed from false. Therefore I have the following suggestions:

In your example you don’t need to have a global variable, and you don’t need to have the initialize() function.

BTW, I always capitalize my functions (i.e. ChangeText()), but that’s me.

Going back to my observations and suggestions, I would suggest you’d write your functions like so:

function checkForInnerTextFeature()
{
	var obj = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;

	return obj;
}

function changeText(elem,changeVal){
    if(!checkForInnerTextFeature()){
        elem.textContent = changeVal;
    }else{
        elem.innerText = changeVal;
    }
}

See, you have one function and one variable less. You don’t even need to call the checkForInnerTextFeature() function on an onload event, there’s no need for that. You can call it whenever you call the changeText() function and the rest of the code will execute accordingly. Other than that your code looks nice.

BTW, innerText is not a feature, is a property, so I’d suggest also to change the name of your function to CheckForInnerTextProperty() or something similar.

27 01 2007
Dharshana Jagoda (15:14:39) :

Alternatively

function changeText(elem,changeVal){
if(elem.textContent){
elem.textContent = changeVal;
}else{
elem.innerText = changeVal;
}
}

or if you want you can test for innerText . It is recomended that you check for the availability of a property of a method this way.

27 01 2007
Juan Wong (16:06:07) :

Dharshana,

You said: “It is recomended that you check for the availability of a property of a method this way”.

I don’t quiet understand why it’s ‘recommended’ the way you put it. To me, it’s just another way to check for the property support. Besides the ‘amount’ of code used, it’s not so different from doing it like in my example (or the use of a function for that matter):

var hasInnerText =
(document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;
30 01 2007
delphi329 (23:51:47) :

why you need to check the innerText property on the body element and not the dom element getting called?

function changeTextById(elm, value){
if (elm instanceof “string”) {
elm = document.getElementById(elm);
}

if (elm.textContent) {
elm.textContent = value;
}else{
elm.innerText = value;
}
}

isn’t that enough

31 01 2007
Juan Wong (00:13:26) :

delphi329,

The answer to your question is right there in the article. Read it again and you’ll find it.

Basically, it all depends on what you need to do. If you’re gonna affect one element only, sure, they way you put it should work fine.

22 03 2007
Alex Roberts (12:09:02) :

The problem with textContent is that it doesn’t get posted back to a form (in ASP.net) whereas innerText does. I thought Firefox was supposed to be the answer to the ghastly compatibility issues of old, but I see it’s still alive and kicking. Shame.

22 03 2007
Juan Wong (12:15:41) :

Alex,

Well, perhaps this happens because ASP.Net and innerText are Microsoft’s. innerText is a proprietary MSIE attribute, go figure.

13 07 2007
Benoît Bruet (23:00:00) :

What about “firstChild.nodeValue” that seems to work in both IE and Firefox (instead of “innerText”/”textContent”) ?

BB

9 08 2007
CoderLab’s Blog » Using the innerText Property in Firefox (17:34:21) :

[...] See also: The textContent and innerText Properties. This post will help you to make the innerText property work in Safari [...]

8 10 2007
Matthew (06:10:14) :

thanks Benoît Bruet you saved my butt, nodeValue works great :D

so much simpler than messing around with innerHTML/textContent

5 11 2007
Efficient Tips (09:40:25) :

@ Benoît Bruet

I tested obj.firstChild.nodeValue in IE (5.5, 6, 7), Opera and Firefox and only IE 5.5 doesnt support nodeValue property, thus making it the most reliable innerText replacement.

Thanks Juan Wong for this article.

5 11 2007
Juan Wong (10:05:03) :

Thank you, Efficent Tips!

21 11 2007
JB (10:04:32) :

nice write-up. Thanks!




LiveSTRONG