2009-06-21 16 views
15

Tengo el siguiente:jQuery: Encontrar el texto de un elemento de lista que contiene una ul anidada

<ul id="list"> 
<li>item1 
    <ul> 
     <li>sub1</li> 
     <li>sub2</li> 
    </ul>  
</li> 
</ul> 

me gustaría responder a un evento li clic y utilizar el texto de la li otro lugar. Sin embargo, si el clic está en un li que contiene un ul anidado, por supuesto obtengo el texto de todos los elementos.

$("#list li").click(function() { 
    alert($(this).text()); 
}); 

devuelve item1sub1sub2, como se esperaba.

No puedo entender cómo obtener solo 'item1' si se hace clic en el elemento 1 li. Intenté lo siguiente (entre otras cosas) sin suerte:

$("#list li").click(function() { 
    alert($(this).filter("ul").text()); 
}); 

¿Alguna idea?

EDITAR

Este es un fragmento de un ejemplo - que podría haber múltiples niveles de profundidad. Tampoco quiero ajustar el texto del elemento de la lista en un lapso u otro marcado.

Respuesta

14

¿Qué tal este enfoque? Clona el objeto, elimina los elementos secundarios del clon y y luego encuentra el contenido del texto.

$("#list li").click(function() { 
    alert($(this).clone().children().remove().end().text()); 
} 

Quizás no es el enfoque más eficaz, pero es totalmente intuitivo, muy ordenado, y que no tiene que ensuciar con su html.

métodos
+0

Gracias, esto funciona bien. He seleccionado esta como la respuesta correcta, pero puedo agregar un lapso alrededor del texto para hacer esto un poco más limpio en este caso. Sigue siendo un buen consejo para situaciones similares. – ScottE

7

está teniendo un momento difícil porque text() hace lo que debería - devuelve el texto de este y todos los elementos secundarios. Lo más fácil es agregar otra etiqueta a cada <li>, y usar esta etiqueta.
Por ejemplo:

<ul id="list"> 
<li><span>item1</span> 
    <ul> 
     <li><span>sub1</span></li> 
     <li><span>sub2</span></li> 
    </</ul>  
</li> 
</ul> 

y entonces usted tiene un selector simple:

$("#list li").click(function() { 
    alert($(this).find("span").eq(0).text()); 
}); 

o, si possilbe (dependiendo de su estilo), es posible añadir el evento al rango de medición:

$("#list span").click(function() { 
    alert($(this).text()); 
}); 

Si no puede agregar estos <span> s (como dice) puede usar jQuery's .contents() para agregarlos, similar a lo que se hizo aquí:

Hide B in <x>A<br/>B</x>

+0

Gracias por hablar sobre '.contents()', ¡eso me ayudó a resolver un problema similar! – thebrokencube

+0

Al agregar s se eliminan los bloques que se pueden hacer clic de los elementos de la lista – Shenaniganz

0

Así que este mecanismo se saca el html del elemento hijo, sustituye a los saltos de línea sin nada, y luego devuelve la cadena sólo hasta el primer carácter "<". También agregué event.stopPropagation para evitar llamar al evento de clic burbujeando hasta el padre.

<script type="text/javascript"> 
$("#list li").click(function(event) { 
    var sourceHTML = $(this).html().replace(/\n/g,'').replace(/<.*/,''); 
    alert(sourceHTML); 
    event.stopPropagation(); 
}); 
</script> 
0

Creo que debe usar cada método. a fin de tratar el siguiente script:

$(document).ready(function() { 
     $('ul').each(function() { 
      $(this).find('li').click(function() { 
       var listItem = this; 
       alert($(listItem).text()); 
      }); 
     }) 
    }); 

con el siguiente marcado

<ul> 
    <li>1</li> 
    <li>2</li> 
    <li>3</li> 
    <li>4</li> 
</ul> 
+1

Hola. text() en un elemento li todavía devolverá el texto completo de todos los elementos secundarios. De hecho, cada() es redundante aquí, es lo mismo que '$ (ul li) .click' – Kobi

1

Esto comprueba si el elemento de la lista tiene hijos y si es así que no deja pasar sólo los nodos de texto y concatena el resultado (en este caso, funcionará para elementos de texto dondequiera que estén puestos en el li). Si solo desea verificar los elementos al inicio, puede evitar el ciclo for y simplemente trabajar con esto.firstChild

$("#list li").click(function(e) { 
    if ($(this).children().length > 0) { 
     var text = ""; 
     for (var i = 0; i < this.childNodes.length; i++) { 
      var node = this.childNodes[i]; 
      if (node.nodeType === 3 && $.trim(node.nodeValue).length > 0) { 
       text += $.trim(node.nodeValue); 
      } 
     } 
     alert(text); 
    } 
    else { 
     alert($(this).text()); 
    } 
    e.stopPropagation(); 
}); 
9

normal DOM permiten acceder a los contenidos de texto de un solo elemento, en lugar de jQuery:

$("#list li").click(function() { 
    alert($(this)[0].firstChild.textContent) 
}); 

firstChild en este caso es la textNode debajo del elemento li

+0

Prefiero este enfoque, ya que también puede usarlo para configurar el texto, sin perder ningún elemento envuelto, a diferencia de la otra versión. (Fuera del alcance de la pregunta, lo sé, pero necesitaba ambos). – Archer

0

Otra forma de lograr misma

$("#list li").click(function() { 
    alert($(this).contents().not('ul,ol').text()); 
}); 
Cuestiones relacionadas