2011-10-25 11 views
20

Pude hacerlo funcionar parcialmente con el selector :contains, pero mi problema es que si un elemento contiene un elemento que contiene el texto, aún lo devuelve. Por ejemplo:selector jQuery para un elemento que contiene texto directamente?

$('div:contains("test")') 

seleccionará dos divs a continuación:

<div>something else 
    <div>test</div> 
</div> 

violín: http://jsfiddle.net/TT7dR/

¿Cómo puedo seleccionar sólo DIVS que "directamente" contiene el texto? Lo que significa que en el ejemplo anterior solo se seleccionaría el div infantil.

ACTUALIZACIÓN:

Solo para aclarar, si estuviera buscando el texto "algo más" en lugar de "prueba", entonces me gustaría sólo para encontrar el div padre.

Respuesta

9

$('div>:contains("test")') no es una solución general, solo funciona para su ejemplo específico. Todavía coincide con cualquier elemento cuyos descendientes contengan el texto test, siempre que su elemento primario sea div.

De hecho, actualmente no hay ningún selector que seleccione solo las fuentes directas de los nodos de texto que contienen el texto de destino. Para hacerlo, debes caminar por el árbol DOM, revisando cada nodo de texto que encuentres para el texto de destino, o escribir un complemento para hacer lo mismo. Sería lento, pero ya no es tan lento como :contains (no es un selector de CSS estándar, por lo que no se admite el selector rápido nativo del navegador).

Aquí hay una función DOM simple que podría usar como punto de partida. Podría mejorarse para encontrar texto en nodos de texto adyacentes (no normalizados), o para ocultarlo en un plugin/selector-extensión.

function findElementsDirectlyContainingText(ancestor, text) { 
    var elements= []; 
    walk(ancestor); 
    return elements; 

    function walk(element) { 
     var n= element.childNodes.length; 
     for (var i= 0; i<n; i++) { 
      var child= element.childNodes[i]; 
      if (child.nodeType===3 && child.data.indexOf(text)!==-1) { 
       elements.push(element); 
       break; 
      } 
     } 
     for (var i= 0; i<n; i++) { 
      var child= element.childNodes[i]; 
      if (child.nodeType===1) 
       walk(child); 
     } 
    } 
} 
1

Esto parece funcionar para mí:

$('div >:contains("test")'); 

http://jsfiddle.net/TT7dR/1/

Fuerza al selector de emparejado :contains ser un hijo directo del elemento <div>

+1

Cerrar pero no del todo allí. Si lo cambió a '$ ('div>: contains (" algo más ")')' alerta 0 cuando debería alertar 1. http://jsfiddle.net/TT7dR/4/ –

3

intento de añadir el mayor de:

$('div>:contains("test")') 
+0

¿Podría explicar cómo funciona esto? ? –

+0

'div' coincide también con el div interno, en realidad no importa, excepto que con'> 'el div externo no se probará para su contenido – ThiefMaster

+0

Cerrar pero no del todo. Si lo cambió a '$ ('div>: contiene (" algo más ")')' alerta 0 cuando debería alertar 1. http://jsfiddle.net/TT7dR/4/ –

4

Es posible que tenga que hacer una consulta eficiente.No utilice esta solución si alguien encuentra un selector que se las arregla para filtrar los elementos secundarios: http://viralpatel.net/blogs/2011/02/jquery-get-text-element-without-child-element.html

$("div:contains('test')") 
    .clone() //clone the element 
    .children() //select all the children 
    .remove() //remove all the children 
    .end() //again go back to selected element 
    .filter(":contains('test')") 

editar: Este recorte anterior es sólo para probar el elemento, en la ejecución que se vería más como esto: http://jsfiddle.net/rkw79/TT7dR/6/

$("div:contains('test')").filter(function() { 
    return (
    $(this).clone() //clone the element 
    .children() //select all the children 
    .remove() //remove all the children 
    .end() //again go back to selected element 
    .filter(":contains('test')").length > 0) 
}).css('border', 'solid 1px black'); 
+0

No es algo para producción, pero sorprendentemente rápido para depuración. – Mahn

+1

Tenga en cuenta que dado que esto clona los elementos, no puede realizar ningún cambio útil en ellos, ya que está alterando los clones. – Merijn

0

Pruebe lo siguiente: elemento específico

$("div>div:contains(test):only-of-type") 
+0

¿Cómo usar esto? –

+0

did> div se refiere al hijo div cuyo padre es div y contiene prueba y que es de un solo div hijo a padre. –

0

encuentra, pero sin t padres

var elementsContainingText = ($(':contains("' + text + '")', target)).filter(function() { 
    return $(this).contents().filter(function() {return this.nodeType === 3 && this.nodeValue.indexOf(text) !== -1; }).length > 0; 
}); 
4

Solo para completar la base de conocimiento. Si usted necesita para obtener todos los elementos DOM dentro del cuerpo (no sólo DIVS) que contienen texto o caracteres específicos que puede utilizar:

function getNodesThatContain(text) { 
    var textNodes = $(document).find(":not(iframe, script)") 
     .contents().filter( 
      function() { 
      return this.nodeType == 3 
      && this.textContent.indexOf(text) > -1; 
    }); 
    return textNodes.parent(); 
}; 

console.log(getNodesThatContain("test")); 

Espero que ayude.

jsFiddle: http://jsfiddle.net/85qEh/2/

Créditos: DMoses

0

Añadir más alternativa:

if($(selector).text().trim().length) { 
    var thetext = $(selector).contents().filter(function(){ 
    return this.nodeType === 3;      
    }).text().trim();  

    console.log(thetext);    

} 

Se seleccionará el texto solamente y eliminar cualquier elemento con la etiqueta!

Reference

Cuestiones relacionadas