"innerText" работает в IE, но не в Firefox
У меня есть некоторый код JavaScript, который работает в IE, содержащий следующее:
myElement.innerText = "foo";
Однако, похоже, что свойство "innerText" не работает в Firefox. Есть ли какой-нибудь аналог Firefox? Или есть более общее свойство кросс-браузера, которое можно использовать?
15 ответов
Firefox использует W3C-совместимое свойство textContent.
Я думаю, Safari и Opera также поддерживают это свойство.
Обновление: я написал сообщение в блоге, детализирующее все различия намного лучше.
Firefox использует стандарт W3C Node::textContent
, но его поведение "немного" отличается от такового у проприетарного MSHTML innerText
(также скопировано Opera некоторое время назад среди десятков других возможностей MSHTML).
Прежде всего, textContent
представление пробелов отличается от innerText
один. Во-вторых, и что более важно, textContent
включает в себя все содержимое тега SCRIPT, в то время как innerText нет.
Просто чтобы сделать вещи более интересными, Opera - помимо реализации стандартных textContent
- решил также добавить MSHTML's innerText
но изменил его, чтобы действовать как textContent
- т.е. включая содержание сценария (на самом деле, textContent
а также innerText
в Opera, кажется, дают идентичные результаты, вероятно, просто псевдонимы друг с другом).
textContent
это часть Node
интерфейс, тогда как innerText
это часть HTMLElement
, Это, например, означает, что вы можете "получить" textContent
но нет innerText
из текстовых узлов:
var el = document.createElement('p');
var textNode = document.createTextNode('x');
el.textContent; // ""
el.innerText; // ""
textNode.textContent; // "x"
textNode.innerText; // undefined
Наконец, Safari 2.x также содержит ошибки innerText
реализация. В сафари innerText
работает правильно, только если элемент не скрыт (через style.display == "none"
) ни осиротевший из документа. Иначе, innerText
приводит к пустой строке.
Я играл с textContent
абстракция (чтобы обойти эти недостатки), но это оказалось довольно сложным.
Лучше всего сначала определить свои точные требования и следовать оттуда. Часто можно просто снять метки с innerHTML
элемента, а не иметь дело со всеми возможными textContent
/ innerText
отклонения.
Другая возможность, конечно, состоит в том, чтобы обходить дерево DOM и рекурсивно собирать текстовые узлы.
Если вам нужно только установить текстовое содержимое, а не получить его, вот тривиальная версия DOM, которую вы можете использовать в любом браузере; для него не требуется расширение IE innerText или свойство textContent DOM Level 3 Core.
function setTextContent(element, text) {
while (element.firstChild!==null)
element.removeChild(element.firstChild); // remove all existing content
element.appendChild(document.createTextNode(text));
}
JQuery обеспечивает .text()
метод, который можно использовать в любом браузере. Например:
$('#myElement').text("Foo");
Согласно ответу Prakash K, Firefox не поддерживает свойство innerText. Таким образом, вы можете просто проверить, поддерживает ли пользовательский агент это свойство, и действовать соответственно, как показано ниже:
function changeText(elem, changeVal) {
if (typeof elem.textContent !== "undefined") {
elem.textContent = changeVal;
} else {
elem.innerText = changeVal;
}
}
Действительно простая строка Javascript может получить текст "без тегов" во всех основных браузерах...
var myElement = document.getElementById('anyElementId');
var myText = (myElement.innerText || myElement.textContent);
Обратите внимание, что Element::innerText
свойство не будет содержать текст, который был скрыт стилем CSS " display:none
"в Google Chrome (также он будет отбрасывать контент, который был замаскирован другими техниками CSS (включая font-size:0, color:transparent и некоторые другие подобные эффекты, которые делают текст не визуализируемым каким-либо видимым способом)).
Другие свойства CSS также учитываются:
- Сначала анализируется стиль "display:" внутренних элементов, чтобы определить, разделяет ли он содержимое блока (например, "display:block", который является значением по умолчанию для элементов блока HTML во встроенной таблице стилей браузера, и чье поведение не было переопределено ваш собственный стиль CSS); в этом случае новая строка будет вставлена в значение свойства innerText. Это не произойдет со свойством textContent.
- Также будут учитываться свойства CSS, которые генерируют встроенное содержимое: например, встроенный элемент
<br \>
который генерирует встроенную новую строку, также генерирует новую строку в значении innerText. - Стиль display: inline не вызывает новой строки ни в textContent, ни в innerText.
- Стиль "display: table" генерирует новые строки вокруг таблицы и между строками таблицы, но "display: table-cell" генерирует символ табуляции.
- Свойство position: absolute (используется с display: block или display: inline, это не имеет значения) также приведет к вставке разрыва строки.
- Некоторые браузеры также включают разделение пробелов на один пробел.
Но Element::textContent
будет по-прежнему содержать ВСЕ содержимое внутренних текстовых элементов независимо от применяемого CSS, даже если они невидимы. И никакие дополнительные символы новой строки или пробелы не будут сгенерированы в textContent, который просто игнорирует все стили и структуру и встроенные / блочные или позиционированные типы внутренних элементов.
Операция копирования / вставки с использованием выделения мышью отбрасывает скрытый текст в формате обычного текста, который помещается в буфер обмена, поэтому он не будет содержать все в textContent
, но только то, что внутри innerText
(после генерации пробелов / новой строки, как указано выше).
Оба свойства затем поддерживаются в Google Chrome, но их содержание может отличаться. Старые браузеры по-прежнему включали в innetText все, что и сейчас содержит textContent (но их поведение в связи с генерацией пробелов / новых строк было несовместимым).
jQuery разрешит эти несоответствия между браузерами, используя метод ".text()", добавленный к проанализированным элементам, которые он возвращает с помощью запроса $(). Внутренне это решает трудности, просматривая HTML DOM, работая только с уровнем "узла". Так что он вернет что-то, похожее на стандартный textContent.
Предостережение заключается в том, что этот метод jQuery не будет вставлять лишние пробелы или разрывы строк, которые могут быть видны на экране, вызванные подэлементами (например, <br />
) содержания.
Если вы разрабатываете некоторые сценарии для обеспечения доступности, и ваша таблица стилей анализируется для неауристического рендеринга, например, плагинов, используемых для связи со средством чтения Брайля, этот инструмент должен использовать textContent, если он должен включать определенные знаки пунктуации, которые добавляются в промежутки, стилизованные с помощью "display: none" и обычно включаются в страницы (например, для верхних индексов / подписок), в противном случае innerText будет очень запутанным для читателя Брайля.
Тексты, скрытые с помощью хитростей CSS, теперь обычно игнорируются основными поисковыми системами (которые также будут анализировать CSS ваших HTML-страниц, а также будут игнорировать тексты, не имеющие контрастных цветов на фоне) с использованием анализатора HTML/CSS и свойства DOM "innerText" точно так же, как в современных визуальных браузерах (по крайней мере, это невидимое содержимое не будет проиндексировано, поэтому скрытый текст не может быть использован в качестве трюка для принудительного включения некоторых ключевых слов на странице для проверки ее содержимого); но этот скрытый текст будет по-прежнему отображаться на странице результатов (если страница все еще была квалифицирована из индекса, который будет включен в результаты), используя свойство textContent вместо полного HTML для удаления дополнительных стилей и сценариев.
Если вы назначите какой-либо простой текст в любом из этих двух свойств, это перезапишет внутреннюю разметку и примененные к ней стили (только назначенный элемент сохранит свой тип, атрибуты и стили), поэтому оба свойства будут содержать одинаковое содержимое., Однако некоторые браузеры теперь больше не поддерживают запись в innerText и позволяют перезаписывать только свойство textContent (вы не можете вставлять разметку HTML при записи в эти свойства, поскольку специальные символы HTML будут правильно кодироваться с использованием числовых ссылок на символы, которые будут отображаться буквально., если вы тогда читаете innerHTML
собственность после назначения innerText
или же textContent
,
innerText
был добавлен в Firefox и должен быть доступен в выпуске FF45: https://bugzilla.mozilla.org/show_bug.cgi?id=264412
Черновик спецификации был написан и, как ожидается, будет включен в стандарт HTML в будущем: http://rocallahan.github.io/innerText-spec/, https://github.com/whatwg/html/issues/465
Обратите внимание, что в настоящее время реализации Firefox, Chrome и IE несовместимы. В будущем мы можем ожидать, что Firefox, Chrome и Edge будут сходиться, в то время как старый IE остается несовместимым.
Смотрите также: https://github.com/whatwg/compat/issues/5
myElement.innerText = myElement.textContent = "foo";
Изменить (спасибо Mark Amery за комментарий ниже): Делайте это таким образом, только если вы вне разумных сомнений знаете, что ни один код не будет полагаться на проверку существования этих свойств, как (например) jQuery. Но если вы используете jQuery, вы, вероятно, просто используете функцию "text" и делаете $('#myElement'). Text ('foo'), как показывают некоторые другие ответы.
Как и в 2016 году от Firefox v45, innerText
работает на Firefox, посмотрите на его поддержку: http://caniuse.com/
Если вы хотите, чтобы он работал на предыдущих версиях Firefox, вы можете использовать textContent
, которая лучше поддерживает Firefox, но хуже на старых версиях IE: http://caniuse.com/
Это был мой опыт с innerText
, textContent
, innerHTML
и значение:
// 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
т.е. = Internet Explorer, FF = Firefox, Ch = Google Chrome. примечание 1: ff работает до тех пор, пока значение не будет удалено с помощью backspace - см. примечание Ray Vega выше. примечание 2: работает немного в chrome - после обновления оно не изменяется, затем вы щелкаете мышью и возвращаетесь в поле, и появляется значение. Лучший из лота elem.value = changeVal
; который я не комментировал выше.
Как насчет этого?
//$elem is the jQuery object passed along.
var $currentText = $elem.context.firstChild.data.toUpperCase();
** Мне нужно было сделать мой верхний регистр.
Нашел это здесь:
<!--[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]-->
Просто репост из комментариев под оригинальным постом. innerHTML работает во всех браузерах. Спасибо Стефита.
myElement.innerHTML = "foo";
Также возможно подражать innerText
поведение в других браузерах:
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, '&').replace(/>/g, '>').replace(/</g, '<').replace(/\n/g, "<br />\n");
}
});
}