9 ответов:
var text = $(".title").contents().filter(function() { return this.nodeType == Node.TEXT_NODE; }).text();Это получает
contentsвыбранного элемента и применяет к нему функцию фильтра. Функция filter возвращает только текстовые узлы (т. е. узлы сnodeType == Node.TEXT_NODE).
Если вы имеете в виду получить значение из первого текстового узла в элементе, этот код будет работать:
var oDiv = document.getElementById("MyDiv"); var firstText = ""; for (var i = 0; i < oDiv.childNodes.length; i++) { var curNode = oDiv.childNodes[i]; if (curNode.nodeName === "#text") { firstText = curNode.nodeValue; break; } }вы можете увидеть это в действии здесь: http://jsfiddle.net/ZkjZJ/
другое собственное решение JS, которое может быть полезно для "сложных" или глубоко вложенных элементов, - использовать NodeIterator. Поставить
NodeFilter.SHOW_TEXTв качестве второго аргумента ("whatToShow") и повторите только дочерние элементы текстового узла элемента.var root = document.getElementById('...'), iter = document.createNodeIterator (root, NodeFilter.SHOW_TEXT), textnode; while (textnode = iter.nextNode()) { // do something with the text node }вы также можете использовать
TreeWalker. Разница между ними заключается в том, чтоNodeIteratorявляется простым линейным итератором, в то время какTreeWalkerпозволяет перемещаться через братьев и предков, а также.
$('.title').clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element .text(); //get the text of element
версия ES6, которая возвращает первый # текстовый узел content
const extract = (node) => { const text = Array.from(node.childNodes).find(child => child.NodeType === Node.TEXT_NODE); return text && text.textContent.trim(); }
Это будет игнорировать пробелы, а так, ваш никогда не получил пустые textNodes..код с использованием ядра Javascript.
var oDiv = document.getElementById("MyDiv"); var firstText = ""; for (var i = 0; i < oDiv.childNodes.length; i++) { var curNode = oDiv.childNodes[i]; whitespace = /^\s*$/; if (curNode.nodeName === "#text" && !(whitespace.test(curNode.nodeValue))) { firstText = curNode.nodeValue; break; } }проверьте его на jsfiddle : -http://jsfiddle.net/webx/ZhLep/
Чистый JavaScript: Минимализм
во-первых, всегда имейте это в виду при поиске текста в DOM.
эта проблема заставит вас обратить внимание на структуру вашего XML / HTML.
в этом чистом примере JavaScript я учитываю возможность нескольких текстовых узлов что может быть чередовать с другими видами узлы. Однако изначально я не выношу суждения о пробелах, оставляя эту задачу фильтрации другому коду.
в этой версии я передаю
NodeListin от вызова / клиентского кода./** * Gets strings from text nodes. Minimalist. Non-robust. Pre-test loop version. * Generic, cross platform solution. No string filtering or conditioning. * * @author Anthony Rutledge * @param nodeList The child nodes of a Node, as in node.childNodes. * @param target A positive whole number >= 1 * @return String The text you targeted. */ function getText (nodeList, target) { var trueTarget = target - 1; var length = nodeList.length; // Because you may have many child nodes. for (var i = 0; i < length; i++) { if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) { return nodeList[i].nodeValue; // Done! No need to keep going. } } return null; }конечно, путем тестирования
node.hasChildNodes()во-первых, не было бы необходимости использовать цикл предварительного тестирования./** * Gets strings from text nodes. Minimalist. Non-robust. Post-test loop version. * Generic, cross platform solution. No string filtering or conditioning. * * @author Anthony Rutledge * @param nodeList The child nodes of a Node, as in node.childNodes. * @param target A positive whole number >= 1 * @return String The text you targeted. */ function getText (nodeList, target) { var trueTarget = target - 1; var length = nodeList.length; var i = 0; do { if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) { return nodeList[i].nodeValue; // Done! No need to keep going. } i++; } while (i < length); return null; }
Чистый JavaScript: Надежный
функции
getTextById()использует две вспомогательные функции:getStringsFromChildren()иfilterWhitespaceLines().
getStringsFromChildren ()
/** * Collects strings from child text nodes. * Generic, cross platform solution. No string filtering or conditioning. * * @author Anthony Rutledge * @version 6.0 * @param parentNode An instance of the Node interface, such as an Element. object. * @return Array of strings, or null. * @throws TypeError if the parentNode is not a Node object. */ function getStringsFromChildren(parentNode) { var strings = []; // The hopeful output; var nodeList; var length; if (!parentNode instanceof Node) { throw new TypeError("The parentNode parameter expects an instance of a Node."); } if (!parentNode.hasChildNodes()) { return null; // We are done. Node may resemble <element></element> } nodeList = parentNode.childNodes; length = nodeList.length; for (var i = 0; i < length; i++) { if (nodeList[i].nodeType === Node.TEXT_NODE) { strings.push(nodeList[i].nodeValue); } } if (strings.length > 0) { return strings; } return null; }
filterWhitespaceLines()
/** * Filters an array of strings to remove whitespace lines. * Generic, cross platform solution. * * @author Anthony Rutledge * @version 6.0 * @param textArray a String associated with the id attribute of an Element. * @return Array of strings that are not lines of whitespace, or null. * @throws TypeError if the textArray param is not of type Array. */ function filterWhitespaceLines(textArray) { var filteredArray = []; // The hopeful output. var whitespaceLine = /(?:^\s+$)/; // Non-capturing Regular Expression. if (!textArray instanceof Array) { throw new TypeError("The textArray parameter expects an instance of a Array."); } for (var i = 0; i < textArray.length; i++) { if (!whitespaceLine.test(textArray[i])) { // If it is not a line of whitespace. filteredArray.push(textArray[i].trim()); // Trimming here is fine. } } if (filteredArray.length > 0) { return filteredArray ; // Leave selecting and joining strings for a specific implementation. } return null; // No text to return. }
getTextById ()
/** * Gets strings from text nodes. Robust. * Generic, cross platform solution. * * @author Anthony Rutledge * @version 6.0 * @param id A String associated with the id property of an Element. * @return Array of strings, or null. * @throws TypeError if the id param is not of type String. * @throws TypeError if the id param cannot be used to find a node by id. */ function getTextById(id) { var textArray = null; // The hopeful output. var idDatatype = typeof id; // Only used in an TypeError message. var node; // The parent node being examined. try { if (idDatatype !== "string") { throw new TypeError("The id argument must be of type String! Got " + idDatatype); } node = document.getElementById(id); if (node === null) { throw new TypeError("No element found with the id: " + id); } textArray = getStringsFromChildren(node); if (textArray === null) { return null; // No text nodes found. Example: <element></element> } textArray = filterWhitespaceLines(textArray); if (textArray.length > 0) { return textArray; // Leave selecting and joining strings for a specific implementation. } } catch (e) { console.log(e.message); } return null; // No text to return. }затем возвращаемое значение (массив или null) отправляется в клиентский код, где оно должно быть обработано. Будем надеяться, что массив должен иметь элементы реального текста, а не строки пробельных.
пустые строки (
"") являются не возвращается, потому что вам нужен текстовый узел, чтобы правильно указать наличие допустимого текста. Возвращение ("") может создать ложное впечатление, что текстовый узел существует, что приводит кого-то к предположению, что они могут изменить текст, изменив значение.nodeValue. Это значение равно false, поскольку текстовый узел не существует в случае пустой строки.Пример 1:
<p id="bio"></p> <!-- There is no text node here. Return null. -->Пример 2:
<p id="bio"> </p> <!-- There are at least two text nodes ("\n"), here. -->в проблема возникает, когда вы хотите, чтобы ваш HTML легко читался, разделяя его. Теперь, даже если нет никакого читаемого человеком действительного текста,Есть еще текстовые узлы с новой строки (
"\n") символы в своем.nodeValueсвойства.люди видят примеры один и два как функционально эквивалентные-пустые элементы, ожидающие заполнения. Дом отличается от человеческого мышления. Вот почему
getStringsFromChildren()функция должна определить, существуют ли текстовые узлы и собрать.nodeValueзначения в массив.for (var i = 0; i < length; i++) { if (nodeList[i].nodeType === Node.TEXT_NODE) { textNodes.push(nodeList[i].nodeValue); } }в Примере два, два текстовых узла существуют и
getStringFromChildren()вернет.nodeValueобоих из них ("\n"). Однако,filterWhitespaceLines()использует регулярное выражение для фильтрации строк из чистых пробелов символов.возвращается
nullвместо перевода строки ("\n") символы форма лжи клиенту / вызывающий код? В человеческом смысле-нет. В терминах дома-да. Однако, проблема здесь получение текста, а не редактирование оно. нет человеческого текста для возврата к вызывающему коду.никогда нельзя знать, сколько символов новой строки может появиться в чьем-то HTML. Создание счетчика, который ищет" второй " символ новой строки, является ненадежным. Он может и не существовать.
конечно, дальше по линии, вопрос редактирование текста в пустой
<p></p>элемент с дополнительными пробелами (Пример 2) может означать уничтожение (возможно, пропуск) всех, кроме одного текстового узла между a теги абзаца, чтобы гарантировать, что элемент содержит именно то, что он должен отображать.независимо от того, за исключением случаев, когда вы делаете что-то экстраординарное, вам понадобится способ определить, какой текстовый узел
.nodeValueсвойство имеет истинный, читаемый человеком текст, который вы хотите изменить.filterWhitespaceLinesмы уже на полпути туда.var whitespaceLine = /(?:^\s+$)/; // Non-capturing Regular Expression. for (var i = 0; i < filteredTextArray.length; i++) { if (!whitespaceLine.test(textArray[i])) { // If it is not a line of whitespace. filteredTextArray.push(textArray[i].trim()); // Trimming here is fine. } }на данный момент у вас может быть выход, который выглядит так:
["Dealing with text nodes is fun.", "Some people just use jQuery."]нет никакой гарантии, что эти два строки соседствуют друг с другом в DOM, поэтому соединяя их с
.join()может получиться неестественный композит. Вместо этого в коде, который вызываетgetTextById(), вам нужно выбрать, с какой строкой вы хотите работать.
вы также можете использовать XPath
text()тест узла, чтобы получить только текстовые узлы. Напримерvar target = document.querySelector('div.title'); var iter = document.evaluate('text()', target, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE); var node; var want = ''; while (node = iter.iterateNext()) { want += node.data; }
Comments