'innerText' funktioniert im IE, aber nicht in Firefox


289

Ich habe JavaScript-Code, der im IE funktioniert und Folgendes enthält:

myElement.innerText = "foo";

Es scheint jedoch, dass die Eigenschaft 'innerText' in Firefox nicht funktioniert. Gibt es ein Firefox-Äquivalent? Oder gibt es eine allgemeinere, browserübergreifende Eigenschaft, die verwendet werden kann?


3
Dies sollte es tun myElement.innerHTML = "foo";
Stefita

Dadurch wird der gesamte HTML-Code im Objekt durch den angegebenen Wert ersetzt.
OMG Ponys

24
Hier erleichtern Bibliotheken wie jQuery das Leben, da sie browserübergreifende Inkonsistenzen wie diese beseitigen, indem Sie ein Standardframework verwenden können.
Dan Diplo

Könnte aber trotzdem passen, wenn es kein HTML gibt, um das man sich kümmern muss.
Alex Polo

21
Sagen Sie uns also, wie Sie diese browserübergreifende Alternative verwenden können, anstatt nur zu sagen, dass dies möglich ist (was nicht konstruktiv ist).
SasQ

Antworten:


249

Firefox verwendet die W3C-kompatible textContent- Eigenschaft.

Ich denke, Safari und Opera unterstützen diese Eigenschaft ebenfalls.



2
@ Bob Ab dem 22. Februar 2016 ist es immer noch nicht.
Krillgar

@krillgar Es ist für Firefox 45 geplant, das in der Woche vom 8. März veröffentlicht wird. Es ist bereits in der aktuellen Beta-Version und seit einiger Zeit in Aurora. Praktisch bedeutet dies, dass Sie mit der Entwicklung von Websites beginnen können, die innerTextnur verwendet werden, und erwarten, dass diese in naher Zukunft auf allen aktuellen Browsern und auch auf dem alten IE (mit möglichen Macken) funktionieren.
Bob

1
FTR: unterscheidet innerTextsich grundlegend von textContentund ist tatsächlich sehr nützlich (überraschenderweise von einer vermuteten IE-Eigenart ...): innerTextversucht, eine ungefähre Darstellung der tatsächlichen Darstellung des Textes im Browser zu geben, ganz anders als das textContent, das nur etwa das Tag- zurückgibt. Entfernen der Markup-Quelle , Hinzufügen von geringem Wert oder sogar zusätzliche Probleme (wie der Verlust von Wortgrenzen).
Gr.

innerText wird 2019 in Version 64 immer noch nicht unterstützt.
Tony Dong

285

Update : Ich habe einen Blog-Beitrag geschrieben, in dem alle Unterschiede viel besser beschrieben werden.


Firefox verwendet den W3C-Standard Node::textContent, aber sein Verhalten unterscheidet sich "geringfügig" von dem von MSHTML innerText(das vor einiger Zeit auch von Opera unter Dutzenden anderer MSHTML-Funktionen kopiert wurde).

Erstens unterscheidet sich die textContentWhitespace-Darstellung von innerTexteiner. Zweitens, und was noch wichtiger ist, textContent umfasst es den gesamten Inhalt des SCRIPT-Tags , während innerText dies nicht tut.

Um die Dinge unterhaltsamer zu gestalten, hat Opera - neben der Implementierung des Standards textContent- beschlossen, auch MSHTMLs hinzuzufügen, diese innerText jedoch dahingehend geändert, dass sie alstextContent SCRIPT-Inhalte dienen (tatsächlich textContentund innerTextin Opera scheinen sie identische Ergebnisse zu liefern, wahrscheinlich nur untereinander). .

textContentist Teil der NodeSchnittstelle, während innerTextTeil von HTMLElement. Dies bedeutet zum Beispiel, dass Sie "abrufen" können, textContentaber nicht innerTextvon Textknoten:

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

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

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

Schließlich hat Safari 2.x auch eine fehlerhafte innerTextImplementierung. innerTextFunktioniert in Safari nur dann ordnungsgemäß, wenn ein Element style.display == "none"im Dokument weder ausgeblendet (via ) noch verwaist ist. Andernfalls innerTextentsteht eine leere Zeichenfolge.

Ich habe mit textContentAbstraktion gespielt (um diese Mängel zu umgehen), aber es stellte sich als ziemlich komplex heraus .

Am besten definieren Sie zuerst Ihre genauen Anforderungen und folgen von dort aus. Es ist oft möglich, Tags einfach innerHTMLvon einem Element zu entfernen, anstatt alle möglichen textContent/ innerTextAbweichungen zu behandeln.

Eine andere Möglichkeit besteht natürlich darin, den DOM-Baum zu durchlaufen und Textknoten rekursiv zu sammeln.


35
Chrome unterstützt auch innerText, daher scheint Firefox der einzige große Browser zu sein, der dies NICHT unterstützt. Und IE ist der einzige Browser, der textContent NICHT unterstützt.
Mike Nelson

7
@mike - Aber es scheint, dass es innerTextin Chrome 60x langsamer ist . jsperf.com/text-content/3
gblazex

8
textContentwird jetzt in IE9 + unterstützt, aber Firefox wird immer noch nicht unterstützt innerText(obwohl sie vor outerHTMLwenigen Tagen den eingeführten IE hinzugefügt haben).
Kangax

1
Für diejenigen, die IE8 noch unterstützen müssen, gibt es hier eine ziemlich vollständige Node.textContentShim: github.com/usmonster/aight/blob/node-textcontent-shim/js/… (hoffentlich bald in aight enthalten ).
Noyo


83

Wenn Sie nur Textinhalte festlegen und nicht abrufen müssen, finden Sie hier eine einfache DOM-Version, die Sie in jedem Browser verwenden können. Es ist weder die IE innerText-Erweiterung noch die DOM Level 3 Core textContent-Eigenschaft erforderlich.

function setTextContent(element, text) {
    while (element.firstChild!==null)
        element.removeChild(element.firstChild); // remove all existing content
    element.appendChild(document.createTextNode(text));
}

Sofern JavaScript keinen "! ==" -Operator hat, sollte dieser Operator in der zweiten Zeile nur "! =" Sein.
RexE

23
@RexE: JavaScript hat einen !==Operator, der umgekehrt ist ===. Der typsensitive Vergleich, der von ===/ verwendet wird, !==ist normalerweise den losen Komparatoren ==/ vorzuziehen !=.
Bobince

Im Internet Explorer funktioniert dies nicht, um den Text von Skript-Tags festzulegen (ich habe sie für eine Vorlage verwendet). Sie haben `scriptTagElement.text = 'meine Vorlage {{hier}}' gesetzt;
Christopher Tarquini

Ich musste sehr viel nachdenken, um zu verstehen, warum Sie die Schleife verwendet haben (und ich würde sie !==nullübrigens komplett verwerfen ), anstatt nur die Schleife durch zu ersetzen element.innerHTML=''(die genau die gleiche Arbeit wie die Schleife ausführen soll, und dann erinnerte ich mich). .: Tabellen in (Legacy-) IE ... ericvasilik.com/2006/07/code-karma.html Könnte ich vorschlagen, eine kurze Beschreibung der "versteckten" und fast nie dokumentierten "Nebenwirkung" des createTextNodeErsetzens von Amp lt hinzuzufügen und gt zu ihren jeweiligen HTML-Zeichenentitäten? Ein Link zu seinem genauen Verhalten wäre großartig!
GitaarLAB


22

Gemäß der Antwort von Prakash K unterstützt Firefox die innerText-Eigenschaft nicht. Sie können also einfach testen, ob der Benutzeragent diese Eigenschaft unterstützt, und wie folgt vorgehen:

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

2
'textContent' in elem wäre einfacher
Jamie Pate

if (elem.textContent! = null) wäre auch einfacher!
Elmue

14

Eine wirklich einfache Zeile Javascript kann den "nicht taggy" Text in allen Hauptbrowsern erhalten ...

var myElement = document.getElementById('anyElementId');
var myText = (myElement.innerText || myElement.textContent);

2
Es gibt ein Problem mit diesem (zumindest in IE8): Wenn innerText eine leere Zeichenfolge ist und textContent undefiniert ist, wird (myElement.innerText || myElement.textContent) undefiniert.
Magnus

1
Neben dem von @Magnus festgestellten Fehler ist es auch erwähnenswert, dass es signifikante Unterschiede in der Art textContentund Weise gibt und innerTextLeerzeichen melden , die für einige Anwendungsfälle von Bedeutung sein können.
Mark Amery

2
Fügen Sie einfach einen weiteren hinzu ||, dh: var myText = (myElement.innerText || myElement.textContent || "") ;um einen undefinierten Wert zu überwinden.
PeterM

6

Beachten Sie, dass die Element::innerTextEigenschaft nicht den Text enthält, der durch den CSS-Stil " display:none" in Google Chrome ausgeblendet wurde (und den Inhalt löscht, der durch andere CSS-Techniken maskiert wurde (einschließlich Schriftgröße: 0, Farbe: transparent und)) einige andere ähnliche Effekte, die dazu führen, dass der Text nicht sichtbar gerendert wird).

Andere CSS-Eigenschaften werden ebenfalls berücksichtigt:

  • Zuerst wird der "display:" - Stil der inneren Elemente analysiert, um festzustellen, ob er einen Blockinhalt begrenzt (z. B. "display: block", der die Standardeinstellung für HTML-Blockelemente im integrierten Stylesheet des Browsers ist und dessen Verhalten nicht überschrieben wurde Ihren eigenen CSS-Stil); In diesem Fall wird eine neue Zeile in den Wert der innerText-Eigenschaft eingefügt. Dies ist bei der Eigenschaft textContent nicht der Fall.
  • Die CSS-Eigenschaften, die Inline-Inhalte generieren, werden ebenfalls berücksichtigt: Beispielsweise <br \>generiert das Inline-Element , das eine Inline-Newline generiert, auch eine Newline im Wert von innerText.
  • Der Stil "display: inline" verursacht weder in textContent noch in innerText eine neue Zeile.
  • Der Stil "display: table" generiert Zeilenumbrüche um die Tabelle und zwischen Tabellenzeilen, "display: table-cell" generiert jedoch ein Tabellierungszeichen.
  • Die Eigenschaft "position: absolute" (wird mit display: block oder display: inline verwendet, spielt keine Rolle) führt auch dazu, dass ein Zeilenumbruch eingefügt wird.
  • Einige Browser enthalten auch eine einzelne Leerzeichen-Trennung zwischen den Bereichen

Enthält Element::textContentjedoch ALLE Inhalte innerer Textelemente unabhängig vom angewendeten CSS, auch wenn sie unsichtbar sind. In textContent werden keine zusätzlichen Zeilenumbrüche oder Leerzeichen generiert, bei denen lediglich alle Stile und die Struktur sowie Inline- / Block- oder positionierte Typen innerer Elemente ignoriert werden.

Beim Kopieren / Einfügen mit der Mausauswahl wird der verborgene Text im textContentNur -Text-Format, das in die Zwischenablage innerTexteingefügt wird, verworfen , sodass nicht alles in der Datei enthalten ist , sondern nur das, was sich darin befindet (nach der Generierung von Leerzeichen / Zeilenumbrüchen wie oben). .

Beide Eigenschaften werden dann in Google Chrome unterstützt, ihr Inhalt kann dann jedoch unterschiedlich sein. Ältere Browser, die immer noch in innetText enthalten sind, ähneln dem, was textContent jetzt enthält (aber ihr Verhalten in Bezug auf die damalige Erzeugung von Leerzeichen / Zeilenumbrüchen war inkonsistent).

jQuery löst diese Inkonsistenzen zwischen Browsern mithilfe der Methode ".text ()", die zu den analysierten Elementen hinzugefügt wird, die über eine $ () - Abfrage zurückgegeben werden. Intern löst es die Schwierigkeiten, indem es in das HTML-DOM schaut und nur mit der "Knoten" -Ebene arbeitet. Es wird also etwas zurückgegeben, das eher dem Standardtextinhalt ähnelt.

Die Einschränkung besteht darin, dass diese jQuery-Methode keine zusätzlichen Leerzeichen oder Zeilenumbrüche einfügt, die möglicherweise auf dem Bildschirm durch Unterelemente (wie <br />) des Inhalts sichtbar sind .

Wenn Sie einige Skripte für die Barrierefreiheit entwerfen und Ihr Stylesheet für nicht-akustisches Rendern analysiert wird, z. B. Plugins für die Kommunikation mit einem Braille-Reader, sollte dieses Tool den Textinhalt verwenden, wenn es die spezifischen Interpunktionszeichen enthalten muss, die in mit gestalteten Bereichen hinzugefügten Bereichen hinzugefügt werden "display: none", die normalerweise in Seiten enthalten sind (z. B. für hochgestellte / tiefgestellte Zeichen), andernfalls ist der innerText für den Braille-Reader sehr verwirrend.

Von CSS-Tricks ausgeblendete Texte werden jetzt normalerweise von großen Suchmaschinen ignoriert (die auch das CSS Ihrer HTML-Seiten analysieren und Texte ignorieren, die keine kontrastierenden Farben im Hintergrund haben), indem sie einen HTML / CSS-Parser und die DOM-Eigenschaft verwenden "innerText" genau wie in modernen visuellen Browsern (zumindest dieser unsichtbare Inhalt wird nicht indiziert, sodass versteckter Text nicht als Trick verwendet werden kann, um die Aufnahme einiger Schlüsselwörter in die Seite zu erzwingen, um den Inhalt zu überprüfen); Dieser versteckte Text wird jedoch weiterhin auf der Ergebnisseite angezeigt (wenn die Seite noch für den Index qualifiziert war, um in die Ergebnisse aufgenommen zu werden). Verwenden Sie dazu die Eigenschaft "textContent" anstelle des vollständigen HTML-Codes, um die zusätzlichen Stile und Skripte zu entfernen.

Wenn Sie in einer dieser beiden Eigenschaften Klartext zuweisen, werden das innere Markup und die darauf angewendeten Stile überschrieben (nur das zugewiesene Element behält seinen Typ, seine Attribute und Stile bei), sodass beide Eigenschaften denselben Inhalt enthalten . Einige Browser berücksichtigen das Schreiben in innerText jetzt jedoch nicht mehr und lassen Sie nur die textContent-Eigenschaft überschreiben (Sie können beim Schreiben in diese Eigenschaften kein HTML-Markup einfügen, da HTML-Sonderzeichen ordnungsgemäß mit numerischen Zeichenreferenzen codiert werden, um buchstäblich angezeigt zu werden , wenn Sie dann die innerHTMLEigenschaft nach der Zuweisung von innerTextoder lesen textContent.


1
Tatsächlich sind in Chrome / WebKits "Schriftgröße: 0", "Farbe: transparent", "Deckkraft: 0", "Texteinzug: -9999px" usw. enthalten innerText. In meinen Tests werden nur "Anzeige: keine" und "Sichtbarkeit: versteckt" ignoriert.
Kangax

5
myElement.innerText = myElement.textContent = "foo";

Bearbeiten (danke an Mark Amery für den Kommentar unten): Tun Sie dies nur so, wenn Sie zweifelsfrei wissen, dass kein Code darauf angewiesen ist, die Existenz dieser Eigenschaften zu überprüfen, wie dies beispielsweise bei jQuery der Fall ist. Wenn Sie jedoch jQuery verwenden, verwenden Sie wahrscheinlich nur die Funktion "text" und führen $ ('# myElement'). Text ('foo') aus, wie einige andere Antworten zeigen.


4
-1; Das ist eine schlechte Idee. Es ist äußerst üblich, dass Code - einschließlich Code in Bibliotheken wie jQuery - auf das Vorhandensein der Eigenschaften innerTextoder überprüft, um textContentzu entscheiden, welche verwendet werden sollen. Wenn Sie beide auf eine Zeichenfolge setzen, wird der Code anderer Personen, der auf das Element einwirkt, fälschlicherweise erkennen, dass der Browser beide Eigenschaften unterstützt. Folglich kann sich dieser Code schlecht verhalten.
Mark Amery

JQuery $ ('# myElement'). Val () funktioniert für Cross-Browser.
Tony Dong

4

innerTextwurde zu Firefox hinzugefügt und sollte in der FF45-Version verfügbar sein: https://bugzilla.mozilla.org/show_bug.cgi?id=264412

Ein Entwurf einer Spezifikation wurde geschrieben und wird voraussichtlich in Zukunft in den HTML-Lebensstandard aufgenommen: http://rocallahan.github.io/innerText-spec/ , https://github.com/whatwg/html/issues/ 465

Beachten Sie, dass derzeit die Firefox-, Chrome- und IE-Implementierungen nicht kompatibel sind. In Zukunft können wir wahrscheinlich erwarten, dass Firefox, Chrome und Edge konvergieren, während der alte IE nicht kompatibel ist.

Siehe auch: https://github.com/whatwg/compat/issues/5


Gibt es eine Polyfüllung?
serv-inc

1
@user Es kommt wirklich darauf an, was du brauchst. Wenn Sie ältere Versionen von Firefox nicht unterstützen müssen und sich nicht um die geringfügigen Unterschiede in der Implementierung kümmern, verwenden Sie einfach innerText. Wenn dies textContentein akzeptabler Fallback ist und Sie alte FX unterstützen müssen, verwenden Sie (innerText || textContent). Wenn Sie eine identische Implementierung in allen Browsern wünschen, gibt es meines Erachtens keine spezifische Polyfüllung dafür, aber einige Frameworks (z. B. jQuery) implementieren möglicherweise bereits etwas Ähnliches - siehe die anderen Antworten auf dieser Seite.
Bob

1
Die Funktionalität von innerText: das heißt: der sichtbare Text auf einer Seite in Firefox> = 38 (für ein Addon) Zumindest sollten die <script>Tags vollständig weggelassen werden. jQuery's $('#body').text()hat bei mir nicht funktioniert. Aber als Workaround innerText || textContentist das in Ordnung. Danke dir.
serv-inc

@user Ja, wenn Sie Fx 38 unterstützen müssen, trifft diese Antwort nicht wirklich zu. Sie müssen vorerst mit den Einschränkungen / Unterschieden von leben textContent.
Bob

1

Was ist mit so etwas?

//$elem is the jQuery object passed along.

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

** Ich musste meine Großbuchstaben machen.


1
Mistlösung; Dies funktioniert nicht, wenn das Element mehr als einen einzelnen Textknoten enthält.
Mark Amery


0

Das war meine Erfahrung mit innerText, textContent, innerHTML, und Wert:

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

dh = Internet Explorer, ff = Firefox, ch = Google Chrome. Anmerkung 1: ff funktioniert so lange, bis der Wert mit der Rücktaste gelöscht wurde - siehe Anmerkung von Ray Vega oben. Hinweis 2: Funktioniert etwas in Chrom - nach dem Update bleibt es unverändert, dann klicken Sie weg und klicken zurück in das Feld und der Wert wird angezeigt. Das Beste von allem ist elem.value = changeVal; was ich oben nicht kommentiert habe.


1
bin es nur ich oder ignorieren Sie die OP-Frage absolut? Er hat nach innerText / textContent gefragt, und Sie sprechen hauptsächlich über Eingaben.
Dementic

Diese Antwort ist sehr schwer zu lesen. Andererseits bin ich nicht davon überzeugt, dass der Inhalt genug Wert hat, um ihn aufzuräumen.
Mark Amery

-1

Nur Reposting von Kommentaren unter dem ursprünglichen Beitrag. innerHTML funktioniert in allen Browsern. Danke stefita.

myElement.innerHTML = "foo";


1
-1; innerHTMList kein angemessener Ersatz für textContent/ es innerTextsei denn, Sie können sicher sein, dass der von Ihnen zugewiesene Text keine Tags oder andere HTML-Syntax enthält. Für alle vom Benutzer bereitgestellten Daten haben Sie definitiv keine Garantie. Es ist gefährlich, diesen Ansatz ohne diese Einschränkung voranzutreiben, da dies zu XSS- Sicherheitslücken führen kann . Bei so vielen sicheren Ansätzen gibt es keinen Grund, diesen überhaupt in Betracht zu ziehen.
Mark Amery

Mark, ich verstehe, dass innerHTML eine normale Methode ist, um Daten in HTML-Elemente wie div, span, p zu schreiben. Ich verwende es, um zurückgegebene JSON-Daten zu verarbeiten. Es ist auch in JQuery ...
Leonid Alzhin

1
Wenn Sie aus einer JSON-Antwort eine beliebige Zeichenfolge erhalten und diese einem Element zuweisen .innerHTML, ist Ihr Code fehlerhaft und Sie sind möglicherweise anfällig für XSS. Was passiert, wenn diese Zeichenfolge ist "<script>alert(1)</script>"?
Mark Amery

1
@MarkAmery: HTML5 gibt an, dass ein <script>über eingefügtes Tag innerHTMLnicht ausgeführt werden soll. Dies schützt ältere Browser jedoch nicht. Außerdem innerHTMLwürde HTML5 zum Beispiel NICHT schützen "<img src='x' onerror='alert(1)'>".
GitaarLAB

-1

fand dies hier:

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

Eine Erklärung wäre schön! Außerdem gibt es hier etwas seltsames Zeug; Warum sollte ein bedingter Kommentar verwendet werden, um die Ausführung auf IE> = 8 zu beschränken, anstatt nur auf IE 8 abzuzielen, wenn IE> = 9 nativ unterstützt textContentwird ? Es ist auch erwähnenswert, dass da innerTextund textContentunterschiedliche Verhaltensweisen haben, über den Code nicht treu ist textContentShim - das potentiell wichtig ist, aber nicht unbedingt offensichtlich!
Mark Amery

Vielen Dank für den Hinweis auf den Fehler, es sollte IE <= 8
Simonarame

-2

Es ist auch möglich, innerTextVerhalten in anderen Browsern zu emulieren :

 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");
         }
     });
 }

Ich suche nur nach Problemen auf der Oberseite meines Kopfes, der Setter ist für pres kaputt, da er die Zeilenumbrüche verdoppelt. Ich vermute, hier stimmt mehr nicht.
Mark Amery
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.