Как получить текстовый узел элемента?



<div class="title">
I am text node
<a class="edit">Edit</a>
</div>


Я хочу получить "я текстовый узел", не хочу удалять тег" редактировать " и нуждаюсь в кросс-браузерном решении.

512   9  

9 ответов:

var text = $(".title").contents().filter(function() {
  return this.nodeType == Node.TEXT_NODE;
}).text();

Это получает contents выбранного элемента и применяет к нему функцию фильтра. Функция filter возвращает только текстовые узлы (т. е. узлы с nodeType == Node.TEXT_NODE).

вы можете получить nodeValue первого childNode с помощью

$('.title')[0].childNodes[0].nodeValue

http://jsfiddle.net/TU4FB/

Если вы имеете в виду получить значение из первого текстового узла в элементе, этот код будет работать:

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 позволяет перемещаться через братьев и предков, а также.

.text() - for jquery

$('.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.

MDN-пробелы в DOM

эта проблема заставит вас обратить внимание на структуру вашего XML / HTML.

в этом чистом примере JavaScript я учитываю возможность нескольких текстовых узлов что может быть чередовать с другими видами узлы. Однако изначально я не выношу суждения о пробелах, оставляя эту задачу фильтрации другому коду.

в этой версии я передаю NodeList in от вызова / клиентского кода.

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

    Ничего не найдено.