'innerText' berfungsi di IE, tetapi tidak di Firefox

289

Saya memiliki beberapa kode JavaScript yang berfungsi di IE yang berisi yang berikut:

myElement.innerText = "foo";

Namun, tampaknya properti 'innerText' tidak berfungsi di Firefox. Apakah ada yang setara dengan Firefox? Atau adakah properti lintas browser yang lebih umum yang dapat digunakan?

sinar
sumber
3
Ini harus melakukannya dengan myElement.innerHTML = "foo";
stefita
Itu akan menggantikan SEMUA HTML di dalam objek dengan nilai yang disediakan.
OMG Ponies
24
Di sinilah perpustakaan seperti jQuery membuat hidup lebih mudah karena mereka mengurus ketidakkonsistenan lintas-browser seperti ini dengan memungkinkan Anda menggunakan kerangka kerja standar.
Dan Diplo
Tapi mungkin masih cocok jika tidak ada HTML untuk diurus.
Alex Polo
21
Jadi beri tahu kami cara menggunakan alternatif lintas-peramban ini alih-alih hanya mengatakan bahwa itu mungkin (yang tidak konstruktif).
SasQ

Jawaban:

249

Firefox menggunakan properti textContent yang sesuai dengan W3C .

Saya kira Safari dan Opera juga mendukung properti ini.

Prakash K
sumber
2
@ Bob Sampai 22 Februari 2016 masih belum.
krillgar
@krillgar Ini dijadwalkan untuk Firefox 45, yang akan dirilis minggu 8 Maret. Ini sudah dalam rilis beta saat ini, dan telah berada di aurora untuk sementara waktu. Apa artinya ini secara praktis adalah Anda dapat mulai mengembangkan situs innerTexthanya menggunakan dan mengharapkannya berfungsi (dengan kemungkinan quirks) pada semua browser saat ini dalam waktu dekat, dan juga IE-lama.
Bob
1
FTR: innerTextadalah sangat berbeda dari textContent, dan benar-benar sangat berguna (mengejutkan dari IE permainan kata-kata dianggap ...): innerTextmencoba untuk memberikan perkiraan bagaimana teks sebenarnya disajikan dalam browser, benar-benar tidak seperti textContentyang kembali hanya tentang tag- sumber markup dilucuti , menambahkan sedikit nilai, atau bahkan masalah ekstra (seperti hilangnya batas kata).
Sz.
innerText masih belum mendukung di 2019 pada versi 64.
Tony Dong
285

Pembaruan : Saya menulis posting blog yang merinci semua perbedaan jauh lebih baik.


Firefox menggunakan standar W3C Node::textContent, tetapi perilakunya berbeda "sedikit" dari milik MSHTML innerText(disalin oleh Opera juga, beberapa waktu lalu, di antara lusinan fitur MSHTML lainnya).

Pertama-tama, textContentrepresentasi spasi putih berbeda dari innerTextsatu. Kedua, dan yang lebih penting, textContent termasuk semua konten tag SCRIPT , sedangkan innerText tidak.

Hanya untuk membuat hal-hal lebih menghibur, Opera - selain menerapkan standar textContent- memutuskan untuk juga menambahkan MSHTML innerText tetapi mengubahnya untuk bertindak sebagaitextContent - yaitu termasuk konten SCRIPT (pada kenyataannya, textContentdan innerTextdi Opera tampaknya menghasilkan hasil yang identik, mungkin hanya saling alias) .

textContentadalah bagian dari Nodeantarmuka, sedangkan innerTextbagian dari HTMLElement. Ini, misalnya, berarti Anda dapat "mengambil" textContenttetapi tidak innerTextdari simpul teks:

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

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

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

Akhirnya, Safari 2.x juga memiliki innerTextimplementasi buggy . Di Safari, innerTextberfungsi dengan baik hanya jika suatu elemen tidak disembunyikan (melalui style.display == "none") atau menjadi yatim dari dokumen. Jika tidak, innerTexthasil dalam string kosong.

Saya bermain dengan textContentabstraksi (untuk mengatasi kekurangan ini), tetapi ternyata agak rumit .

Anda bertaruh terbaik adalah menentukan terlebih dahulu persyaratan persis Anda dan mengikuti dari sana. Seringkali dimungkinkan untuk menghapus tag innerHTMLdari suatu elemen, alih-alih menangani semua kemungkinan textContent/ innerTextpenyimpangan.

Kemungkinan lain, tentu saja, adalah berjalan di pohon DOM dan mengumpulkan node teks secara rekursif.

Kangax
sumber
35
Chrome juga mendukung innerText, jadi sepertinya Firefox adalah satu-satunya browser utama yang TIDAK mendukungnya. Dan IE adalah satu-satunya browser yang TIDAK mendukung textContent.
mike nelson
7
@ Mike - Tapi sepertinya 60x lebih lambat untuk digunakan innerTextdi Chrome. jsperf.com/text-content/3
gblazex
8
textContentsekarang didukung di IE9 +, tetapi Firefox masih tidak mendukung innerText(walaupun mereka menambahkan IE-diperkenalkan outerHTMLhanya beberapa hari yang lalu).
kangax
1
Bagi mereka yang masih perlu mendukung IE8, ada Node.textContentkemajuan yang cukup lengkap sedang berlangsung di sini: github.com/usmonster/aight/blob/node-textcontent-shim/js/… (semoga segera dimasukkan dalam aight ).
Noyo
83

Jika Anda hanya perlu mengatur konten teks dan tidak mengambil, inilah versi DOM sepele yang dapat Anda gunakan di browser apa pun; tidak memerlukan ekstensi IE innerText IE atau properti DOM Level 3 Core textContent.

function setTextContent(element, text) {
    while (element.firstChild!==null)
        element.removeChild(element.firstChild); // remove all existing content
    element.appendChild(document.createTextNode(text));
}
bobince
sumber
Kecuali jika JavaScript memiliki operator "! ==", saya pikir operator di baris kedua seharusnya "! =".
RexE
23
@RexE: JavaScript memang memiliki !==operator, kebalikan dari ===. Perbandingan jenis-sensitif yang digunakan oleh ===/ !==biasanya lebih disukai daripada komparator longgar ==/ !=.
bobince
Di internet explorer ini tidak berfungsi untuk mengatur teks tag skrip (saya menggunakannya untuk templat). Anda telah menetapkan `scriptTagElement.text = 'templat saya {{sini}}';
Christopher Tarquini
Saya harus berpikir sangat keras untuk memahami mengapa Anda menggunakan loop (dan saya akan membuang !==nullsepenuhnya dengan cara) daripada hanya mengganti loop dengan element.innerHTML=''(yang ditetapkan untuk melakukan pekerjaan yang sama persis dengan loop dan kemudian saya ingat .. .: tabel di (legacy-) IE ... ericvasilik.com/2006/07/code-karma.html Mungkin saya sarankan menambahkan deskripsi singkat tentang 'efek samping ' yang tersembunyi dan hampir tidak pernah didokumentasikan 'efek samping' dari createTextNodepenggantian amp lt dan gt ke entitas karakter html masing-masing? Tautan ke perilaku yang tepat akan lebih baik!
GitaarLAB
26

jQuery menyediakan .text()metode yang dapat digunakan di browser apa pun. Sebagai contoh:

$('#myElement').text("Foo");
pengguna161433
sumber
22

Sesuai jawaban Prakash K, Firefox tidak mendukung properti innerText. Jadi, Anda cukup menguji apakah agen pengguna mendukung properti ini dan melanjutkannya seperti di bawah ini:

function changeText(elem, changeVal) {
    if (typeof elem.textContent !== "undefined") {
        elem.textContent = changeVal;
    } else {
        elem.innerText = changeVal;
    }
}
rism
sumber
2
'textContent' di elem akan lebih sederhana
Jamie Pate
jika (elem.textContent! = null) juga akan lebih mudah!
Elmue
14

Baris Javascript yang sangat sederhana bisa mendapatkan teks "non-taggy" di semua browser utama ...

var myElement = document.getElementById('anyElementId');
var myText = (myElement.innerText || myElement.textContent);
Dave
sumber
2
Ada masalah dengan yang itu (setidaknya di IE8): Jika innerText adalah string kosong dan textContent tidak terdefinisi maka (myElement.innerText || myElement.textContent) menjadi tidak terdefinisi.
Magnus
1
Selain bug yang dicatat oleh @Magnus, ada baiknya juga menyadari fakta bahwa ada perbedaan signifikan dalam cara textContentdan innerTextmelaporkan spasi putih yang mungkin penting untuk beberapa kasus penggunaan.
Mark Amery
2
Cukup tambahkan yang lain ||, yaitu: var myText = (myElement.innerText || myElement.textContent || "") ;untuk mengatasi nilai yang tidak ditentukan.
PeterM
6

Perhatikan bahwa Element::innerTextproperti tidak akan mengandung teks yang telah disembunyikan oleh gaya CSS " display:none" di Google Chrome (juga akan menjatuhkan konten yang telah disembunyikan oleh teknik CSS lainnya (termasuk ukuran font: 0, warna: transparan, dan beberapa efek serupa lainnya yang menyebabkan teks tidak ditampilkan dengan cara apa pun yang terlihat).

Properti CSS lainnya juga dipertimbangkan:

  • Pertama-tama gaya "tampilan:" elemen dalam diuraikan untuk menentukan apakah ia membatasi konten blok (seperti "tampilan: blok" yang merupakan default elemen blok HTML di stylesheet bawaan browser, dan yang perilakunya tidak ditimpa oleh gaya CSS Anda sendiri); jika demikian baris baru akan dimasukkan dalam nilai properti innerText. Ini tidak akan terjadi dengan properti textContent.
  • Properti CSS yang menghasilkan konten inline juga akan dipertimbangkan: misalnya elemen inline <br \>yang menghasilkan baris inline juga akan menghasilkan baris baru dalam nilai innerText.
  • Gaya "display: inline" tidak menyebabkan baris baru di textContent atau innerText.
  • Gaya "display: table" menghasilkan baris baru di sekitar tabel dan di antara baris tabel, tetapi "display: table-cell" akan menghasilkan karakter tabulasi.
  • Properti "position: absolute" (digunakan dengan tampilan: blok atau tampilan: inline, itu tidak masalah) juga akan menyebabkan jeda baris dimasukkan.
  • Beberapa browser juga akan menyertakan pemisahan spasi tunggal antara bentang

Tetapi Element::textContentakan tetap mengandung SEMUA konten elemen teks dalam secara independen dari CSS yang diterapkan bahkan jika mereka tidak terlihat. Dan tidak ada baris baru atau spasi putih akan dihasilkan dalam textContent, yang mengabaikan semua gaya dan struktur dan inline / blok atau jenis elemen dalam yang diposisikan.

Operasi salin / rekat menggunakan pilihan mouse akan membuang teks tersembunyi dalam format teks biasa yang dimasukkan ke clipboard, sehingga tidak akan berisi semua yang ada di textContent, tetapi hanya apa yang ada di dalamnya.innerText (setelah spasi putih / generasi baris baru seperti di atas) .

Kedua properti kemudian didukung di Google Chrome, tetapi kontennya mungkin berbeda. Browser lama masih termasuk dalam innetText, semua seperti isi textContent sekarang (tetapi perilaku mereka dalam kaitannya dengan generasi spasi putih / baris baru tidak sesuai).

jQuery akan menyelesaikan ketidakkonsistenan ini di antara browser menggunakan metode ".text ()" yang ditambahkan ke elemen yang diuraikan yang dikembalikan melalui kueri $ (). Secara internal, ini memecahkan kesulitan dengan melihat ke dalam DOM HTML, hanya bekerja dengan level "simpul". Jadi itu akan mengembalikan sesuatu yang lebih mirip dengan konten teks standar.

Peringatannya adalah bahwa metode jQuery ini tidak akan menyisipkan spasi tambahan atau jeda baris yang mungkin terlihat di layar yang disebabkan oleh subelemen (seperti <br />) konten.

Jika Anda merancang beberapa skrip untuk aksesibilitas dan lembar gaya Anda diuraikan untuk rendering non-aural, seperti plugin yang digunakan untuk berkomunikasi dengan pembaca Braille, alat ini harus menggunakan konten TextContent jika harus menyertakan tanda baca spesifik yang ditambahkan dalam bentang yang ditata dalam bentang yang ditata dengan gaya "display: none" dan yang biasanya disertakan dalam halaman (misalnya untuk superskrip / subskrip), jika tidak, innerText akan sangat membingungkan pembaca Braille.

Teks yang disembunyikan oleh trik CSS sekarang biasanya diabaikan oleh mesin pencari utama (yang juga akan mengurai CSS halaman HTML Anda, dan juga akan mengabaikan teks yang tidak memiliki warna kontras di latar belakang) menggunakan parser HTML / CSS dan properti DOM. "innerText" persis seperti di browser visual modern (setidaknya konten tidak terlihat ini tidak akan diindeks sehingga teks tersembunyi tidak dapat digunakan sebagai trik untuk memaksa dimasukkannya beberapa kata kunci di halaman untuk memeriksa kontennya); tetapi teks tersembunyi ini akan tetap ditampilkan di halaman hasil (jika halaman tersebut masih memenuhi syarat dari indeks untuk dimasukkan dalam hasil), menggunakan properti "textContent" alih-alih HTML lengkap untuk menghapus gaya dan skrip tambahan.

JIKA Anda menetapkan beberapa teks biasa di salah satu dari dua properti ini, ini akan menimpa markup dalam dan gaya yang diterapkan padanya (hanya elemen yang ditugaskan akan menyimpan jenis, atribut, dan gaya), sehingga kedua properti kemudian akan berisi konten yang sama . Namun, beberapa browser sekarang tidak lagi menghormati penulisan ke innerText, dan hanya akan membiarkan Anda menimpa properti textContent (Anda tidak dapat menyisipkan markup HTML saat menulis ke properti ini, karena karakter khusus HTML akan dikodekan dengan benar menggunakan referensi karakter numerik untuk muncul secara harfiah , jika Anda membaca innerHTMLproperti setelah penugasan innerTextatau textContent.

verdy_p
sumber
1
Sebenarnya "ukuran font: 0", "warna: transparan", "opacity: 0", "indentasi teks: -9999px", dll. Semuanya termasuk dalam Chrome / WebKit innerText. Dalam pengujian saya, hanya "tampilan: tidak ada" dan "visibilitas: tersembunyi" yang diabaikan.
kangax
5
myElement.innerText = myElement.textContent = "foo";

Sunting (terima kasih kepada Mark Amery untuk komentar di bawah): Hanya lakukan dengan cara ini jika Anda tahu tanpa keraguan bahwa tidak ada kode yang akan mengandalkan memeriksa keberadaan properti ini, seperti (misalnya) jQuery melakukannya. Tetapi jika Anda menggunakan jQuery, Anda mungkin hanya akan menggunakan fungsi "text" dan melakukan $ ('# myElement'). Text ('foo') seperti yang ditunjukkan beberapa jawaban lainnya.

Kwateco
sumber
4
-1; ini ide yang buruk. Sangat umum untuk kode - termasuk kode di perpustakaan seperti jQuery - untuk memeriksa keberadaan innerTextatau textContentproperti untuk memutuskan mana yang akan digunakan. Dengan menyetel keduanya ke string, Anda akan membuat kode orang lain yang bekerja pada elemen tersebut secara keliru mendeteksi bahwa browser mendukung kedua properti; akibatnya kode tersebut dapat berperilaku tidak pantas.
Mark Amery
JQuery $ ('# myElement'). Val () berfungsi untuk lintas browser.
Tony Dong
4

innerTexttelah ditambahkan ke Firefox dan harus tersedia dalam rilis FF45: https://bugzilla.mozilla.org/show_bug.cgi?id=264412

Draf spesifikasi telah ditulis dan diharapkan dapat dimasukkan ke dalam standar hidup HTML di masa mendatang: http://rocallahan.github.io/innerText-spec/ , https://github.com/whatwg/html/issues/ 465

Perhatikan bahwa saat ini implementasi Firefox, Chrome dan IE semuanya tidak kompatibel. Ke depan, kita mungkin bisa berharap Firefox, Chrome dan Edge untuk menyatu sementara IE yang lama tetap tidak kompatibel.

Lihat juga: https://github.com/whatwg/compat/issues/5

Bob
sumber
Apakah ada polyfill yang tersedia?
serv-inc
1
@user Sangat tergantung pada apa yang Anda butuhkan. Jika Anda tidak perlu mendukung versi Firefox yang lebih lama dan tidak peduli tentang perbedaan kecil dalam implementasi, gunakan saja innerText. Jika textContentmerupakan fallback yang dapat diterima dan Anda perlu mendukung Fx lama, maka gunakan (innerText || textContent). Jika Anda ingin implementasi yang identik di semua browser, saya tidak percaya ada polyfill khusus untuk ini tetapi beberapa kerangka kerja (misalnya jQuery) mungkin sudah mengimplementasikan sesuatu yang serupa - lihat jawaban lain di halaman ini.
Bob
1
Fungsionalitas innerText, yaitu: Teks yang terlihat di halaman, di Firefox> = 38 (untuk addon) Setidaknya, <script>tag harus dihilangkan sepenuhnya. jQuery $('#body').text()tidak bekerja untuk saya. Tetapi sebagai solusi innerText || textContenttidak apa-apa. Terima kasih.
serv-inc
@ pengguna Ya, jika Anda perlu mendukung Fx 38 maka jawaban ini tidak benar-benar berlaku. Anda harus hidup dengan keterbatasan / perbedaan textContentuntuk saat ini.
Bob
1

Bagaimana dengan sesuatu yang seperti ini?

//$elem is the jQuery object passed along.

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

** Saya perlu membuat huruf besar milik saya.

Webmaster G
sumber
1
Solusi omong kosong; ini tidak berfungsi jika elemen mengandung lebih dari satu simpul teks tunggal.
Mark Amery
0

Ini telah menjadi pengalaman saya dengan innerText, textContent, innerHTML, dan nilai:

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

yaitu = internet explorer, ff = firefox, ch = google chrome. note 1: ff bekerja sampai setelah nilai dihapus dengan backspace - lihat catatan oleh Ray Vega di atas. Catatan 2: berfungsi agak di chrome - setelah pembaruan itu tidak berubah maka Anda klik dan klik kembali ke bidang dan nilai muncul. Yang terbaik dari semuanya adalah elem.value = changeVal; yang saya tidak berkomentar di atas.

Marc
sumber
1
apakah hanya saya? atau apakah abosolutly mengabaikan pertanyaan OP? ia meminta innerText / textContent, dan Anda berbicara tentang input kebanyakan.
Demensik
Jawaban ini sangat sulit dibaca. Di sisi lain, saya tidak yakin konten memiliki nilai yang cukup untuk dirapikan.
Mark Amery
-1

Hanya pengeposan ulang dari komentar di bawah posting asli. innerHTML berfungsi di semua browser. Terima kasih stefita.

myElement.innerHTML = "foo";

Leonid Alzhin
sumber
1
-1; innerHTMLbukan pengganti yang memadai untuk textContent/ innerTextkecuali Anda dapat memastikan bahwa teks yang Anda tetapkan tidak mengandung tag atau sintaks HTML lainnya. Untuk data apa pun yang disediakan oleh pengguna, Anda pasti tidak memiliki jaminan itu. Mendorong pendekatan ini tanpa peringatan itu berbahaya mengingat dapat menyebabkan lubang keamanan XSS . Dengan begitu banyak pendekatan aman yang tersedia, tidak ada alasan untuk mempertimbangkan yang satu ini.
Mark Amery
Mark, pengertian saya adalah bahwa innerHTML adalah cara normal untuk menulis data ke elemen html seperti div, span, p. Saya menggunakannya untuk memproses data JSON yang dikembalikan. Ada di JQuery, juga ...
Leonid Alzhin
1
Jika Anda mendapatkan string sewenang-wenang dari respons JSON dan menetapkannya ke elemen .innerHTML, kode Anda rusak dan Anda berpotensi rentan terhadap XSS. Apa yang terjadi jika string itu "<script>alert(1)</script>"?
Mark Amery
1
@MarkAmery: HTML5 menetapkan bahwa <script>tag yang disisipkan via innerHTMLtidak boleh dijalankan. Tapi itu tidak melindungi browser lama. Juga, HTML5 innerHTMLTIDAK akan melindungi misalnya "<img src='x' onerror='alert(1)'>".
GitaarLAB
-1

temukan ini di sini:

<!--[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]-->
simonarame
sumber
Beberapa penjelasan akan menyenangkan! Juga, ada beberapa hal aneh di sini; mengapa menggunakan komentar kondisional untuk membatasi eksekusi ke IE> = 8, daripada hanya menargetkan IE 8, ketika IE> = 9 mendukung textContentsecara asli ? Perlu juga dicatat bahwa karena innerTextdan textContentmemiliki perilaku yang berbeda, kode di atas bukan textContentshim yang setia - ini berpotensi penting, tetapi belum tentu jelas!
Mark Amery
terima kasih telah menunjukkan kelemahannya, itu ditujukan untuk menjadi IE <= 8
simonarame
-2

Mungkin juga untuk meniru innerTextperilaku di browser lain:

 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");
         }
     });
 }
DitherSky
sumber
Hanya mencari masalah dari atas kepala saya, setter rusak karena pres akan menggandakan baris baru. Saya curiga ada yang salah di sini.
Mark Amery