Usar .text () para recuperar solo texto no nested en tags secundarias

Si tengo html como este:

  • This is some text First span text Second span text
  • Estoy tratando de usar .text() para recuperar solo la cadena “Esto es texto“, pero si tuviera que decir $('#list-item').text() Text $('#list-item').text() , obtendría “This is some textFirst span” textoSegundo lapso de texto “.

    ¿Hay alguna forma de obtener (y posiblemente eliminar, mediante algo como .text("") ) solo el texto libre dentro de una etiqueta, y no el texto dentro de sus tags secundarias?

    El HTML no fue escrito por mí, así que esto es con lo que tengo que trabajar. Sé que sería simple envolver el texto en tags al escribir el html, pero una vez más, el html está escrito previamente.

    Me gustó esta implementación reutilizable basada en el método clone() que se encuentra aquí para obtener solo el texto dentro del elemento padre.

    Código proporcionado para una fácil referencia:

     $("#foo") .clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element .text(); 

    Respuesta simple:

     $("#listItem").contents().filter(function(){ return this.nodeType == 3; })[0].nodeValue = "The text you want to replace with" 

    Esto parece un caso de uso excesivo de jquery para mí. Lo siguiente tomará el texto ignorando los otros nodos:

     document.getElementById("listItem").childNodes[0]; 

    Tendrá que recortar eso, pero obtendrá lo que quiere en una línea fácil.

    EDITAR

    Lo anterior obtendrá el nodo de texto . Para obtener el texto real, usa esto:

     document.getElementById("listItem").childNodes[0].nodeValue; 

    Más fácil y más rápido:

     $("#listItem").contents().get(0).nodeValue 

    Similar a la respuesta aceptada, pero sin clonación:

     $("#foo").contents().not($("#foo").children()).text(); 

    Y aquí hay un complemento jQuery para este propósito:

     $.fn.immediateText = function() { return this.contents().not(this.children()).text(); }; 

    Aquí está cómo usar este plugin:

     $("#foo").immediateText(); // get the text without children 

    no es el código:

     var text = $('#listItem').clone().children().remove().end().text(); 

    simplemente convertirse en jQuery por el bien de jQuery? Cuando las operaciones simples involucran muchos comandos encadenados y ese procesamiento (innecesario), tal vez sea el momento de escribir una extensión jQuery:

     (function ($) { function elementText(el, separator) { var textContents = []; for(var chld = el.firstChild; chld; chld = chld.nextSibling) { if (chld.nodeType == 3) { textContents.push(chld.nodeValue); } } return textContents.join(separator); } $.fn.textNotChild = function(elementSeparator, nodeSeparator) { if (arguments.length<2){nodeSeparator="";} if (arguments.length<1){elementSeparator="";} return $.map(this, function(el){ return elementText(el,nodeSeparator); }).join(elementSeparator); } } (jQuery)); 

    llamar:

     var text = $('#listItem').textNotChild(); 

    los argumentos son en caso de que se encuentre un escenario diferente, como

     
  • some textmore textagain more
  • second textmore textagain more
  • var text = $("li").textNotChild(".....","");

    el texto tendrá valor:

     some textagain more.....second textagain more 

    Tendrá que ser algo adaptado a las necesidades, que dependen de la estructura que se le presente. Para el ejemplo que ha proporcionado, esto funciona:

     $(document).ready(function(){ var $tmp = $('#listItem').children().remove(); $('#listItem').text('').append($tmp); }); 

    Demostración: http://jquery.nodnod.net/cases/2385/run

    Pero es bastante dependiente de que el marcado sea similar a lo que publicaste.

    Prueba esto:

     $('#listItem').not($('#listItem').children()).text() 
     $($('#listItem').contents()[0]).text() 

    Variante corta de la respuesta de Stuart.

    o con get()

     $($('#listItem').contents().get(0)).text() 

    Esta es una vieja pregunta, pero la respuesta principal es muy ineficiente. Aquí hay una mejor solución:

     $.fn.myText = function() { var str = ''; this.contents().each(function() { if (this.nodeType == 3) { str += this.textContent || this.innerText || ''; } }); return str; }; 

    Y solo haz esto:

     $("#foo").myText(); 
     jQuery.fn.ownText = function () { return $(this).contents().filter(function () { return this.nodeType === Node.TEXT_NODE; }).text(); }; 

    Supongo que esta sería una buena solución también, si desea obtener los contenidos de todos los nodos de texto que son hijos directos del elemento seleccionado.

     $(selector).contents().filter(function(){ return this.nodeType == 3; }).text(); 

    Nota: la documentación de jQuery usa un código similar para explicar la función del contenido: https://api.jquery.com/contents/

    PD: También hay una manera un poco más fea de hacerlo, pero esto muestra más a fondo cómo funcionan las cosas, y permite un separador personalizado entre nodos de texto (quizás quieras un salto de línea).

     $(selector).contents().filter(function(){ return this.nodeType == 3; }).map(function() { return this.nodeValue; }).toArray().join(""); 

    simplemente póngalo en un

    o y tome ese $ (‘# listItem font’). text ()

    Lo primero que se me vino a la mente

     
  • This is some text First span text Second span text
  • Se me ocurrió una solución específica que debería ser mucho más eficiente que la clonación y modificación del clon. Esta solución solo funciona con las siguientes dos reservas, pero debería ser más eficiente que la solución actualmente aceptada:

    1. Usted está recibiendo solo el texto
    2. El texto que desea extraer está antes de los elementos secundarios

    Dicho esto, aquí está el código:

     // 'element' is a jQuery element function getText(element) { var text = element.text(); var childLength = element.children().text().length; return text.slice(0, text.length - childLength); } 

    Propongo usar createTreeWalker para encontrar todos los elementos de texto no adjuntos a los elementos html (esta función se puede usar para extender jQuery):

     function textNodesOnlyUnder(el) { var resultSet = []; var n = null; var treeWalker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, function (node) { if (node.parentNode.id == el.id && node.textContent.trim().length != 0) { return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_SKIP; }, false); while (n = treeWalker.nextNode()) { resultSet.push(n); } return resultSet; } window.onload = function() { var ele = document.getElementById('listItem'); var textNodesOnly = textNodesOnlyUnder(ele); var resultingText = textNodesOnly.map(function(val, index, arr) { return 'Text element N. ' + index + ' --> ' + val.textContent.trim(); }).join('\n'); document.getElementById('txtArea').value = resultingText; } 
     
  • This is some text First span text Second span text
  • Al igual que la pregunta, estaba tratando de extraer texto para hacer una sustitución de expresiones regulares del texto, pero estaba teniendo problemas donde mis elementos internos (es decir: ,

    , , etc.) se estaban poniendo también remoto.

    El siguiente código parece funcionar bien y resolvió todos mis problemas.

    Utiliza algunas de las respuestas proporcionadas aquí, pero en particular, solo sustituirá el texto cuando el elemento sea de nodeType === 3 .

     $(el).contents().each(function() { console.log(" > Content: %s [%s]", this, (this.nodeType === 3)); if (this.nodeType === 3) { var text = this.textContent; console.log(" > Old : '%s'", text); regex = new RegExp("\\[\\[" + rule + "\\.val\\]\\]", "g"); text = text.replace(regex, value); regex = new RegExp("\\[\\[" + rule + "\\.act\\]\\]", "g"); text = text.replace(regex, actual); console.log(" > New : '%s'", text); this.textContent = text; } }); 

    Lo que hace arriba es recorrer todos los elementos del el dado (que simplemente se obtuvo con $("div.my-class[name='some-name']"); Para cada elemento interno, básicamente los ignora Para cada porción de texto (según lo determinado por if (this.nodeType === 3) ) aplicará la sustitución de if (this.nodeType === 3) regulares solo a esos elementos.

    La porción this.textContent = text simplemente reemplaza el texto sustituido, que en mi caso, estaba buscando tokens como [[min.val]] , [[max.val]] , etc.

    Este fragmento de código corto ayudará a cualquiera que trate de hacer lo que la pregunta estaba haciendo … y un poco más.

    Esta es una buena forma para mí

      var text = $('#listItem').clone().children().remove().end().text(); 

    Puedes intentar esto

     alert(document.getElementById('listItem').firstChild.data) 

    Para poder recortar el resultado, use DotNetWala de esta manera:

     $("#foo") .clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element .text() .trim(); 

    Descubrí que usar la versión más corta como document.getElementById("listItem").childNodes[0] no funcionará con trim () de jQuery.

    Use una condición adicional para verificar si innerHTML e innerText son iguales. Solo en esos casos, reemplace el texto.

     $(function() { $('body *').each(function () { console.log($(this).html()); console.log($(this).text()); if($(this).text() === "Search" && $(this).html()===$(this).text()) { $(this).html("Find"); } }) }) 

    http://jsfiddle.net/7RSGh/

    Esto no se ha probado, pero creo que puedes intentar algo como esto:

      $('#listItem').not('span').text(); 

    http://api.jquery.com/not/

    No soy un experto en jquery, pero qué tal,

     $('#listItem').children().first().text()