The textContent and innerText Properties

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

25 Comments

  1. Joe
    Posted July 27, 2006 at 5:27 am | Permalink

    wicked !

    thanks a lot

  2. Posted July 27, 2006 at 8:26 am | Permalink

    glad I can help ;)

  3. Posted July 31, 2006 at 4:30 pm | Permalink

    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;
        }
    
    }
    
  4. Posted July 31, 2006 at 5:28 pm | Permalink

    @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

  5. Beni Rose
    Posted August 30, 2006 at 9:42 pm | Permalink

    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

  6. Ken Odoki-Olam
    Posted December 19, 2006 at 4:23 am | Permalink

    What’s wrong with document.body?

  7. Posted December 19, 2006 at 6:05 am | Permalink

    @Ken,

    It hasn’t been feelin’ well lately…

  8. Posted January 16, 2007 at 7:14 pm | Permalink

    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.

  9. Posted January 16, 2007 at 7:42 pm | Permalink

    @Jesse,

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

  10. Posted January 18, 2007 at 4:07 am | Permalink

    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

  11. Posted January 18, 2007 at 10:48 am | Permalink

    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**

  12. Posted January 18, 2007 at 2:27 pm | Permalink

    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?

  13. Posted January 18, 2007 at 2:34 pm | Permalink

    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);
    
  14. Posted January 18, 2007 at 8:18 pm | Permalink

    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.

  15. Dharshana Jagoda
    Posted January 27, 2007 at 3:14 pm | Permalink

    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.

  16. Posted January 27, 2007 at 4:06 pm | Permalink

    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;
    
  17. delphi329
    Posted January 30, 2007 at 11:51 pm | Permalink

    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

  18. Posted January 31, 2007 at 12:13 am | Permalink

    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.

  19. Posted March 22, 2007 at 12:09 pm | Permalink

    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.

  20. Posted March 22, 2007 at 12:15 pm | Permalink

    Alex,

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

  21. Benoît Bruet
    Posted July 13, 2007 at 11:00 pm | Permalink

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

    BB

  22. Matthew
    Posted October 8, 2007 at 6:10 am | Permalink

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

    so much simpler than messing around with innerHTML/textContent

  23. Posted November 5, 2007 at 9:40 am | Permalink

    @ 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.

  24. Posted November 5, 2007 at 10:05 am | Permalink

    Thank you, Efficent Tips!

  25. JB
    Posted November 21, 2007 at 10:04 am | Permalink

    nice write-up. Thanks!

One Trackback

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