<div class="title">
I am text node
<a class="edit">Edit</a>
</div>
Я хочу получить "Я - текстовый узел", не хочу удалять тег "edit" и мне нужно кроссбраузерное решение.
javascript
jquery
Вал
источник
источник
Ответы:
Это получает значение
contents
выбранного элемента и применяет к нему функцию фильтра. Функция фильтра возвращает только текстовые узлы (т.е. узлы сnodeType == Node.TEXT_NODE
).источник
text()
потому чтоfilter
функция возвращает сами узлы, а не их содержимое.jQuery("*").each(function() { console.log(this.nodeType); })
и получил 1 для всех типов узлов.Вы можете получить nodeValue первого дочернего узла, используя
http://jsfiddle.net/TU4FB/
источник
null
возвращаемое значение.Если вы имеете в виду получить значение первого текстового узла в элементе, этот код будет работать:
Вы можете увидеть это в действии здесь: http://jsfiddle.net/ZkjZJ/
источник
curNode.nodeType == 3
вместо этогоnodeName
.curNode.nodeType == Node.TEXT_NODE
(числовое сравнение быстрее, но curNode.nodeType == 3 не читается - какой узел имеет номер 3?)curNode.NodeType === Node.TEXT_NODE
. Это сравнение происходит в цикле неизвестных возможных итераций. Сравнение двух маленьких чисел лучше, чем сравнение строк разной длины (соображения времени и места). Правильный вопрос в этой ситуации - «какой тип / тип узла у меня есть?», А не «какое у меня имя?» developer.mozilla.org/en-US/docs/Web/API/Node/nodeTypechildNodes
, знайте, что узел элемента может иметь более одного текстового узла. В общем решении может потребоваться указать, какой экземпляр текстового узла в узле элемента вы хотите настроить (первый, второй, третий и т. Д.).Еще одно собственное JS-решение, которое может быть полезно для «сложных» или глубоко вложенных элементов, - это использование NodeIterator . Поместите
NodeFilter.SHOW_TEXT
в качестве второго аргумента («whatToShow») и перебирайте только дочерние текстовые узлы элемента.Вы также можете использовать
TreeWalker
. Разница между ними в том, чтоNodeIterator
это простой линейный итератор, который такжеTreeWalker
позволяет перемещаться через братьев и сестер и предков.источник
Чистый JavaScript: минимализм
Во-первых, всегда помните об этом при поиске текста в DOM.
MDN - Пробелы в DOM
Эта проблема заставит вас обратить внимание на структуру вашего XML / HTML.
В этом примере на чистом JavaScript я учитываю возможность наличия нескольких текстовых узлов, которые могут чередоваться с другими типами узлов. . Однако изначально я не осуждаю пробелы, оставляя эту задачу фильтрации другому коду.
В этой версии я прохожу
NodeList
передаю код вызова / клиента.Конечно, если
node.hasChildNodes()
сначала провести тестирование , не нужно будет использоватьfor
цикл предварительного тестирования .Чистый JavaScript: надежный
Здесь функция
getTextById()
использует две вспомогательные функции:getStringsFromChildren()
иfilterWhitespaceLines()
.getStringsFromChildren ()
filterWhitespaceLines ()
getTextById ()
Затем возвращаемое значение (Array или null) отправляется клиентскому коду, где оно должно быть обработано. Будем надеяться, что массив должен содержать строковые элементы реального текста, а не строки пробелов.
Пустые строки (
""
) не возвращаются, потому что вам нужен текстовый узел, чтобы правильно указать наличие допустимого текста. Returning (""
) может создать ложное впечатление о существовании текстового узла, что заставит кого-то предположить, что он может изменить текст, изменив значение.nodeValue
. Это неверно, потому что текстовый узел не существует в случае пустой строки.Пример 1 :
Пример 2 :
Проблема возникает, когда вы хотите упростить чтение HTML-кода за счет интервалов. Теперь, даже несмотря на отсутствие удобочитаемого допустимого текста, все еще есть текстовые узлы с символами новой строки (
"\n"
) в их.nodeValue
свойствах.Люди рассматривают примеры один и два как функционально эквивалентные - пустые элементы, ожидающие заполнения. Модель DOM отличается от человеческого мышления. Вот почему
getStringsFromChildren()
функция должна определять, существуют ли текстовые узлы, и собирать.nodeValue
значения в массив.Во втором примере два текстовых узла действительно существуют и
getStringFromChildren()
будут возвращать.nodeValue
их обоих ("\n"
). ОднакоfilterWhitespaceLines()
использует регулярное выражение для фильтрации строк, состоящих из чисто пробельных символов.Является ли возврат
null
вместо"\n"
символов новой строки ( ) формой лжи клиентскому / вызывающему коду? Говоря человеческим языком, нет. С точки зрения DOM, да. Однако проблема здесь в получении текста, а не в его редактировании. Нет человеческого текста для возврата к вызывающему коду.Никогда нельзя узнать, сколько символов новой строки может появиться в чьем-либо HTML. Создание счетчика, который ищет «второй» символ новой строки, ненадежно. Возможно, этого не существует.
Конечно, в дальнейшем проблема редактирования текста в пустом
<p></p>
элементе с дополнительными пробелами (пример 2) может означать уничтожение (возможно, пропуск) всех текстовых узлов, кроме одного, между тегами абзаца, чтобы гарантировать, что элемент содержит именно то, что он есть предполагается отображать.В любом случае, за исключением случаев, когда вы делаете что-то необычное, вам понадобится способ определить, какое
.nodeValue
свойство текстового узла имеет истинный, читаемый человеком текст, который вы хотите отредактировать.filterWhitespaceLines
приводит нас на полпути.На этом этапе вы можете получить следующий результат:
Нет гарантии, что эти две строки соседствуют друг с другом в DOM, поэтому их объединение
.join()
может привести к неестественной композиции. Вместо этого в коде, который вызываетgetTextById()
вам нужно выбрать, с какой строкой вы хотите работать.Протестируйте вывод.
Можно добавить
.trim()
внутрь,getStringsFromChildren()
чтобы избавиться от начальных и конечных пробелов (или чтобы превратить кучу пробелов в строку нулевой длины (""
), но как вы можете заранее знать, что каждое приложение, возможно, должно произойти с текстом (строкой) как только он будет найден? Нет, поэтому оставьте это для конкретной реализации и пустьgetStringsFromChildren()
будет общим.Могут быть случаи, когда этот уровень специфичности (
target
и тому подобное) не требуется. Это отлично. В таких случаях используйте простое решение. Однако обобщенный алгоритм позволяет учесть простые и сложные ситуации.источник
Версия ES6, возвращающая содержимое первого #text узла
источник
.from()
для создания экземпляра массива с неглубоким копированием. (2) Использование.find()
для сравнения строк с использованием.nodeName
. Использованиеnode.NodeType === Node.TEXT_NODE
было бы лучше. (3) Возврат пустой строки при отсутствии значенияnull
более верен, если текстовый узел не найден. Если текстовый узел не найден, возможно, потребуется его создать! Если вы вернете пустую строку,""
вы можете создать ложное впечатление, что текстовый узел существует и с ним можно нормально работать. По сути, возвращение пустой строки - это белая ложь, и ее лучше избегать.[...node.childNodes]
для преобразования HTMLCollection в массивы.text() - for jquery
источник
a
элемента: jsfiddle.net/ekHJH.
в начале вашего селектора, что означает, что вы фактически получаете текстtitle
элемента, а не элементы сclass="title"
.innerText
- это старая конвенция IE, принятая недавно. С точки зрения стандартного сценария DOM,node.nodeValue
это способ получения текста текстового узла.Это также будет игнорировать пробелы, так что вы никогда не получили Blank textNodes..code с использованием основного Javascript.
Проверьте это на jsfiddle: - http://jsfiddle.net/webx/ZhLep/
источник
curNode.nodeType === Node.TEXT_NODE
было бы лучше. Использование сравнения строк и регулярного выражения в цикле - решение с низкой производительностью, особенно приoDiv.childNodes.length
увеличении величины . Этот алгоритм решает конкретный вопрос OP, но, возможно, с ужасной ценой производительности. Если расположение или количество текстовых узлов изменяется, то это решение не может гарантировать получение точного вывода. Другими словами, вы не можете настроить таргетинг на нужный текстовый узел. Вы находитесь во власти структуры HTML и расположения текста в нем.Вы также можете использовать
text()
тест узлов XPath, чтобы получить только текстовые узлы. Напримеристочник
Это мое решение в ES6 для создания строки, запрещающей объединенный текст всех дочерних узлов (рекурсивный) . Обратите внимание, что это также посещение корня дочерних узлов.
Это решение было вдохновлено решением https://stackoverflow.com/a/41051238./1300775 .
источник