'innerText' works in IE, but not in Firefox
Asked Answered
F

15

295

I have some JavaScript code that works in IE containing the following:

myElement.innerText = "foo";

However, it seems that the 'innerText' property does not work in Firefox. Is there some Firefox equivalent? Or is there a more generic, cross browser property that can be used?

Foetor answered 31/8, 2009 at 21:17 Comment(6)
This should do it myElement.innerHTML = "foo";Fie
That will replace ALL the HTML within the object with the supplied value.Widera
This is where libraries like jQuery make life easier as they take care of cross-browser inconsistencies like this by enabling you to use a standard framework.Orange
But still might suit if there is no HTML to take care of.Bertie
Never assign some computed value that may include user data in a page to the innerHTML property of elements. This could cause complete break of your page layout by inserting styles or scripts or extra elements that won't parse correctly. It is always safer to assign the innerText or textContent property (note that during assignments, these two properties behave the same when one or both are supported by browsers and are assignable). But for supporting older browsers, it's preferable to assign the inner text using the jQuery's Element::text(string) method.Reavis
So tell us how to use this cross-browser alternative instead of just saying that it's possible (which is not constructive).Reo
C
252

Firefox uses the W3C-compliant textContent property.

I'd guess Safari and Opera also support this property.

Calculable answered 31/8, 2009 at 21:26 Comment(5)
innerText is/will be supported in FF as of 2016.Cappuccino
@Cappuccino As of Feb 22, 2016 it still is not.Backcross
@Backcross It's scheduled for Firefox 45, due to be released week of 8th March. It's already in the current beta release, and has been in aurora for a while. What this practically means is you can start developing sites using innerText only and expect it to work (with possible quirks) on all current browsers in the near future, and old-IE too.Cappuccino
FTR: innerText is profoundly different from textContent, and actually is very useful (surprisingly from a presumed IE quirk...): innerText tries to give an approximation of how the text is actually presented in the browser, totally unlike textContent, which returns just about the tag-stripped markup source, adding little value, or even extra problems (like the loss of word boundaries).Spinneret
innerText still not support in 2019 on version 64.Experimentation
A
289

Update: I wrote a blog post detailing all the differences much better.


Firefox uses W3C standard Node::textContent, but its behavior differs "slightly" from that of MSHTML's proprietary innerText (copied by Opera as well, some time ago, among dozens of other MSHTML features).

First of all, textContent whitespace representation is different from innerText one. Second, and more importantly, textContent includes all of SCRIPT tag contents, whereas innerText doesn't.

Just to make things more entertaining, Opera - besides implementing standard textContent - decided to also add MSHTML's innerText but changed it to act as textContent - i.e. including SCRIPT contents (in fact, textContent and innerText in Opera seem to produce identical results, probably being just aliased to each other).

textContent is part of Node interface, whereas innerText is part of HTMLElement. This, for example, means that you can "retrieve" textContent but not innerText from text nodes:

var el = document.createElement('p');
var textNode = document.createTextNode('x');

el.textContent; // ""
el.innerText; // ""

textNode.textContent; // "x"
textNode.innerText; // undefined

Finally, Safari 2.x also has buggy innerText implementation. In Safari, innerText functions properly only if an element is neither hidden (via style.display == "none") nor orphaned from the document. Otherwise, innerText results in an empty string.

I was playing with textContent abstraction (to work around these deficiencies), but it turned out to be rather complex.

You best bet is to first define your exact requirements and follow from there. It is often possible to simply strip tags off of innerHTML of an element, rather than deal with all of the possible textContent/innerText deviations.

Another possibility, of course, is to walk the DOM tree and collect text nodes recursively.

Anywheres answered 31/8, 2009 at 23:16 Comment(5)
Chrome supports innerText as well, so it seems like Firefox is the only major browser to NOT support it. And IE is the only browser to NOT support textContent.Freebooter
@mike - But it seems it's 60x slower to use innerText in Chrome. jsperf.com/text-content/3Emrick
textContent is now supported in IE9+, but Firefox still doesn't support innerText (although they did add IE-introduced outerHTML just few days ago).Anywheres
For those who still need to support IE8, there's a pretty complete Node.textContent shim in progress here: github.com/usmonster/aight/blob/node-textcontent-shim/js/… (hopefully soon to be included in aight).Widescreen
innerText is/will be supported in FF as of 2016.Cappuccino
C
252

Firefox uses the W3C-compliant textContent property.

I'd guess Safari and Opera also support this property.

Calculable answered 31/8, 2009 at 21:26 Comment(5)
innerText is/will be supported in FF as of 2016.Cappuccino
@Cappuccino As of Feb 22, 2016 it still is not.Backcross
@Backcross It's scheduled for Firefox 45, due to be released week of 8th March. It's already in the current beta release, and has been in aurora for a while. What this practically means is you can start developing sites using innerText only and expect it to work (with possible quirks) on all current browsers in the near future, and old-IE too.Cappuccino
FTR: innerText is profoundly different from textContent, and actually is very useful (surprisingly from a presumed IE quirk...): innerText tries to give an approximation of how the text is actually presented in the browser, totally unlike textContent, which returns just about the tag-stripped markup source, adding little value, or even extra problems (like the loss of word boundaries).Spinneret
innerText still not support in 2019 on version 64.Experimentation
C
83

If you only need to set text content and not retrieve, here's a trivial DOM version you can use on any browser; it doesn't require either the IE innerText extension or the DOM Level 3 Core textContent property.

function setTextContent(element, text) {
    while (element.firstChild!==null)
        element.removeChild(element.firstChild); // remove all existing content
    element.appendChild(document.createTextNode(text));
}
Crinkumcrankum answered 31/8, 2009 at 23:20 Comment(4)
Unless JavaScript has a "!==" operator, I think that operator in the second line should just be "!=".Quill
@RexE: JavaScript does have a !== operator, the inverse of ===. The type-sensitive comparison used by ===/!== is usually preferable to the loose comparators ==/!=.Crinkumcrankum
In internet explorer this doesn't work to set the text of script tags (I was using them for a template). You have set `scriptTagElement.text = 'my template {{here}}';Zeph
I had to think very hard to understand why you used the loop (and I would discard the !==null completely by the way) instead of just replacing the loop with element.innerHTML='' (which is specced to do the exact same work as the loop and then I remembered...: tables in (legacy-)IE... ericvasilik.com/2006/07/code-karma.html Might I suggest adding a short description of the 'hidden' and almost never documented 'side-effect' of createTextNode replacing amp lt and gt to their respective html character entities? A link to it's exact behavior would be grand!Quinquereme
A
27

jQuery provides a .text() method that can be used in any browser. For example:

$('#myElement').text("Foo");
Abbess answered 31/8, 2009 at 23:36 Comment(0)
C
22

As per Prakash K's answer Firefox does not support the innerText property. So you can simply test whether the user agent supports this property and proceed accordingly as below:

function changeText(elem, changeVal) {
    if (typeof elem.textContent !== "undefined") {
        elem.textContent = changeVal;
    } else {
        elem.innerText = changeVal;
    }
}
Christlike answered 31/8, 2009 at 21:57 Comment(2)
'textContent' in elem would be simplerCounterfactual
if (elem.textContent != null) would be easier, too!Vyatka
E
13

A really simple line of Javascript can get the "non-taggy" text in all main browsers...

var myElement = document.getElementById('anyElementId');
var myText = (myElement.innerText || myElement.textContent);
Extrapolate answered 13/6, 2013 at 14:37 Comment(3)
There is a problem with that one (at least in IE8): If innerText is empty string and textContent is undefined then (myElement.innerText || myElement.textContent) becomes undefined.Newson
As well as the bug noted by @Magnus, it's also worth being aware of the fact that there are significant differences in how textContent and innerText report whitespace that may matter for some use cases.Clockwork
Simply add another ||, ie: var myText = (myElement.innerText || myElement.textContent || "") ; to overcome undefined value.Interesting
R
6

Note that the Element::innerText property will not contain the text which has been hidden by CSS style "display:none" in Google Chrome (as well it will drop the content that has been masked by other CSS technics (including font-size:0, color:transparent, and a few other similar effects that cause the text not to be rendered in any visible way).

Other CSS properties are also considered :

  • First the "display:" style of inner elements is parsed to determine if it delimits a block content (such as "display:block" which is the default of HTML block elements in the browser's builtin stylesheet, and whose behavior as not been overriden by your own CSS style); if so a newline will be inserted in the value of the innerText property. This won't happen with the textContent property.
  • The CSS properties that generate inline contents will also be considered : for example the inline element <br \> that generates an inline newline will also generate an newline in the value of innerText.
  • The "display:inline" style causes no newline either in textContent or innerText.
  • The "display:table" style generates newlines around the table and between table rows, but"display:table-cell" will generate a tabulation character.
  • The "position:absolute" property (used with display:block or display:inline, it does not matter) will also cause a line break to be inserted.
  • Some browsers will also include a single space separation between spans

But Element::textContent will still contain ALL contents of inner text elements independantly of the applied CSS even if they are invisible. And no extra newlines or whitespaces will be generated in textContent, which just ignores all styles and the structure and inline/block or positioned types of inner elements.

A copy/paste operation using mouse selection will discard the hidden text in the plain-text format that is put in the clipboard, so it won't contain everything in the textContent, but only what is within innerText (after whitespace/newline generation as above).

Both properties are then supported in Google Chrome, but their content may then be different. Older browsers still included in innetText everything like what textContent now contains (but their behavior in relation with then generation of whitespaces/newlines was inconsistant).

jQuery will solve these inconsistencies between browsers using the ".text()" method added to the parsed elements it returns via a $() query. Internally, it solves the difficulties by looking into the HTML DOM, working only with the "node" level. So it will return something looking more like the standard textContent.

The caveat is that that this jQuery method will not insert any extra spaces or line breaks that may be visible on screen caused by subelements (like <br />) of the content.

If you design some scripts for accessibility and your stylesheet is parsed for non-aural rendering, such as plugins used to communicate with a Braille reader, this tool should use the textContent if it must include the specific punctuation signs that are added in spans styled with "display:none" and that are typically included in pages (for example for superscripts/subscripts), otherwise the innerText will be very confusive on the Braille reader.

Texts hidden by CSS tricks are now typically ignored by major search engines (that will also parse the CSS of your HTML pages, and will also ignore texts that are not in contrasting colors on the background) using an HTML/CSS parser and the DOM property "innerText" exactly like in modern visual browsers (at least this invisible content will not be indexed so hidden text cannot be used as a trick to force the inclusion of some keywords in the page to check its content) ; but this hidden text will be stil displayed in the result page (if the page was still qualified from the index to be included in results), using the "textContent" property instead of the full HTML to strip the extra styles and scripts.

IF you assign some plain-text in any one of these two properties, this will overwrite the inner markup and styles applied to it (only the assigned element will keep its type, attributes and styles), so both properties will then contain the same content. However, some browsers will now no longer honor the write to innerText, and will only let you overwrite the textContent property (you cannot insert HTML markup when writing to these properties, as HTML special characters will be properly encoded using numeric character references to appear literally, if you then read the innerHTML property after the assignment of innerText or textContent.

Reavis answered 30/7, 2012 at 0:16 Comment(1)
Actually "font-size: 0", "color: transparent", "opacity: 0", "text-indent: -9999px", etc. are all included in Chrome/WebKit's innerText. In my tests, only "display: none" and "visibility: hidden" are ignored.Anywheres
T
5
myElement.innerText = myElement.textContent = "foo";

Edit (thanks to Mark Amery for the comment below): Only do it this way if you know beyond a reasonable doubt that no code will be relying on checking the existence of these properties, like (for example) jQuery does. But if you are using jQuery, you would probably just use the "text" function and do $('#myElement').text('foo') as some other answers show.

Thoreau answered 25/9, 2013 at 5:33 Comment(2)
-1; this is a bad idea. It's extremely common for code - including code in libraries like jQuery - to check for the existence of the innerText or textContent properties to decide which one to use. By setting both to a string, you'll make other people's code acting on the element mistakenly detect that the browser supports both properties; consequently that code is liable to misbehave.Clockwork
JQuery $('#myElement').val() works for cross browser.Experimentation
C
5

innerText has been added to Firefox and should be available in the FF45 release: https://bugzilla.mozilla.org/show_bug.cgi?id=264412

A draft spec has been written and is expected to be incorporated into the HTML living standard in the future: http://rocallahan.github.io/innerText-spec/, https://github.com/whatwg/html/issues/465

Note that currently the Firefox, Chrome and IE implementations are all incompatible. Going forward, we can probably expect Firefox, Chrome and Edge to converge while old IE remains incompatible.

See also: https://github.com/whatwg/compat/issues/5

Cappuccino answered 5/1, 2016 at 0:35 Comment(4)
Is there a polyfill available?Locate
@user It really depends on what you need. If you don't need to support older versions of Firefox and don't care about the minor differences in implementation, just use innerText. If textContent is an acceptable fallback and you need to support old Fx, then use (innerText || textContent). If you want an identical implementation across all browsers, I do not believe there's any specific polyfill for this but some frameworks (e.g. jQuery) might already implement something similar - refer to the other answers on this page.Cappuccino
The functionality of innerText, that is: the visible Text on a page, in Firefox >= 38 (for an addon) At least, the <script> tags should be completely omitted. jQuery's $('#body').text() did not work for me. But as a workaround innerText || textContent is ok. Thank you.Locate
@user Yea, if you need to support Fx 38 then this answer doesn't really apply. You'll have to live with the limitations/differences of textContent for now.Cappuccino
L
1

This has been my experience with innerText, textContent, innerHTML, and value:

// elem.innerText = changeVal;  // works on ie but not on ff or ch
// elem.setAttribute("innerText", changeVal); // works on ie but not ff or ch
// elem.textContent = changeVal;  // works on ie but not ff or ch
// elem.setAttribute("textContent", changeVal);  // does not work on ie ff or ch
// elem.innerHTML = changeVal;  // ie causes error - doesn't work in ff or ch
// elem.setAttribute("innerHTML", changeVal); //ie causes error doesn't work in ff or ch
   elem.value = changeVal; // works in ie and ff -- see note 2 on ch
// elem.setAttribute("value", changeVal); // ie works; see note 1 on ff and note 2 on ch

ie = internet explorer, ff = firefox, ch = google chrome. note 1: ff works until after value is deleted with backspace - see note by Ray Vega above. note 2: works somewhat in chrome - after update it is unchanged then you click away and click back into the field and the value appears. The best of the lot is elem.value = changeVal; which I did not comment out above.

Lightless answered 25/9, 2009 at 19:42 Comment(2)
is it just me ? or do abosolutly ignore the OP question ? he asked for innerText/textContent, and you are talking about inputs mostly.Streamway
This answer is very hard to read. On the other hand, I'm not convinced the content has enough value to be worth tidying it up.Clockwork
D
1

As in 2016 from Firefox v45, innerText works on firefox, take a look at its support: http://caniuse.com/#search=innerText

If you want it to work on previous versions of Firefox, you can use textContent, which has better support on Firefox but worse on older IE versions: http://caniuse.com/#search=textContent

Dissolvent answered 19/7, 2016 at 8:42 Comment(0)
E
0

What about something like this?

//$elem is the jQuery object passed along.

var $currentText = $elem.context.firstChild.data.toUpperCase();

** I needed to make mine uppercase.

Ergotism answered 2/2, 2014 at 2:22 Comment(1)
Crap solution; this doesn't work if the element contains anything more than a single text node.Clockwork
B
-1

found this here:

<!--[if lte IE 8]>
    <script type="text/javascript">
        if (Object.defineProperty && Object.getOwnPropertyDescriptor &&
            !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get)
          (function() {
            var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
            Object.defineProperty(Element.prototype, "textContent",
              { // It won't work if you just drop in innerText.get
                // and innerText.set or the whole descriptor.
                get : function() {
                  return innerText.get.call(this)
                },
                set : function(x) {
                  return innerText.set.call(this, x)
                }
              }
            );
          })();
    </script>
<![endif]-->
Blockhead answered 11/5, 2013 at 8:11 Comment(2)
Some explanation would be nice! Also, there's some weird shit in here; why use a conditional comment to restrict execution to IE >= 8, rather than targeting IE 8 solely, when IE >= 9 support textContent natively? It's also worth noting that since innerText and textContent have different behaviours, the code above is not a faithful textContent shim - this is potentially important, but not necessarily obvious!Clockwork
thank you for pointing out the flaw, it was aimed to be IE <= 8Blockhead
P
-1

Just reposting from comments under the original post. innerHTML works in all browsers. Thanks stefita.

myElement.innerHTML = "foo";

Philology answered 5/2, 2015 at 18:0 Comment(4)
-1; innerHTML is not an adequate replacement for textContent/innerText unless you can be certain that the text you are assigning does not contain any tags or other HTML syntax. For any data provided by the user, you definitely don't have that guarantee. Pushing this approach without that caveat is dangerous given that it can lead to XSS security holes. With so many safe approaches available, there's no reason to even consider this one.Clockwork
Mark, my understanding is that innerHTML is a normal way to write data to html elements like div, span, p. I use it to process returned JSON data. It's in JQuery, too...Philology
If you get an arbitrary string from a JSON response and assign it to an element's .innerHTML, your code is broken and you're potentially vulnerable to XSS. What happens if that string is "<script>alert(1)</script>"?Clockwork
@MarkAmery: HTML5 specifies that a <script> tag inserted via innerHTML should not execute. But that doesn't safeguard older browsers. Also, HTML5 innerHTML would NOT safeguard for example "<img src='x' onerror='alert(1)'>".Quinquereme
E
-2

It's also possible to emulate innerText behavior in other browsers:

 if (((typeof window.HTMLElement) !== "undefined") && ((typeof HTMLElement.prototype.__defineGetter__) !== "undefined")) {
     HTMLElement.prototype.__defineGetter__("innerText", function () {
         if (this.textContent) {
             return this.textContent;
         } else {
             var r = this.ownerDocument.createRange();
             r.selectNodeContents(this);
             return r.toString();
         }
     });
     HTMLElement.prototype.__defineSetter__("innerText", function (str) {
         if (this.textContent) {
             this.textContent = str;
         } else {
             this.innerHTML = str.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/\n/g, "<br />\n");
         }
     });
 }
Emotionalize answered 15/7, 2013 at 15:53 Comment(1)
Just looking for problems off the top of my head, the setter is broken for pres since it'll double-up the newlines. I suspect there's more wrong here.Clockwork

© 2022 - 2024 — McMap. All rights reserved.