2009-06-21 8 views
15

Ho il seguente:jQuery: trovato il testo di una voce di elenco che contiene un ul nidificato

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

mi piacerebbe rispondere a un evento li clic e utilizzare il testo del Li altrove. Tuttavia, se il clic è su un li che contiene un ul annidato, ovviamente ottengo il testo di tutti gli elementi.

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

restituisce item1sub1sub2, come previsto.

Non riesco a capire come ottenere solo 'elemento1' se si fa clic sull'elemento 1 li. Ho provato il seguente (tra le altre cose) senza fortuna:

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

Qualche idea?

EDIT

Questo è un frammento di un esempio - potrebbe essere più livelli di profondità. Inoltre, non desidero avvolgere il testo dell'elenco in uno span o in un altro markup.

risposta

14

E questo approccio? Clona l'oggetto, rimuovi i figli del clone e quindi trova il contenuto del testo.

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

Forse non è il metodo più efficiente, ma è del tutto intuitivo, piuttosto ordinato, e non devi fare muck con il codice HTML.

metodi
+0

Grazie, funziona bene. Ho selezionato questa come risposta corretta, ma potrei aggiungere un'estensione attorno al testo per renderlo un po 'più pulito in questo caso. Ancora un buon consiglio per situazioni simili. – ScottE

7

si sta avendo un momento difficile perché text() fa quello che dovrebbe - restituisce il testo di questo e tutti gli elementi figlio. La cosa più semplice da fare è aggiungere un altro tag a ogni <li> e utilizzare questo tag.
Per esempio:

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

e poi ci sono un semplice selettore:

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

o, se possilbe (a seconda del vostro stile), è possibile aggiungere l'evento a campata:

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

Se non è possibile aggiungere questi <span> s (come dici tu) puoi usare jQuery's .contents() per aggiungerli per te, in modo simile a quanto è stato fatto qui:

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

+0

Grazie per aver parlato di '.contents()', che mi ha aiutato a risolvere un problema simile! – thebrokencube

+0

L'aggiunta di s rimuove i blocchi selezionabili dagli elementi dell'elenco – Shenaniganz

0

Quindi questo meccanismo tira fuori il codice HTML l'elemento secondario, sostituisce le nuove righe con niente, e poi restituisce la stringa solo fino al primo carattere "<". Ho anche aggiunto event.stopPropagation per evitare di chiamare l'evento click ribollendo al padre.

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

Penso che sia necessario utilizzare ciascun metodo. in modo da provare il seguente script:

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

con il seguente markup

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

Salve. text() su un elemento li restituirà comunque il testo completo di tutti i bambini. In effetti, ciascuno() è ridondante qui, è lo stesso di '$ (ul li) .click' – Kobi

1

Questo controlla se l'elemento della lista ha dei figli e se sì filtra fuori solo i nodi di testo e concatena il risultato (in questo caso funzionerà per gli elementi di testo ovunque siano messi in li). Se vuoi solo controllare elementi all'inizio, puoi evitare il ciclo for e lavorare con questo.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

normale DOM permettono di accedere ai contenuti di testo per un solo elemento, piuttosto che jquery:

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

firstChild in questo caso è il TextNode sotto l'elemento li

+0

Preferisco questo approccio in quanto puoi anche utilizzarlo per impostare il testo, senza perdere alcun elemento avvolto, a differenza dell'altra versione. (Al di fuori della portata della domanda, lo so, ma avevo bisogno di entrambi). – Archer

0

Un altro modo per ottenere lo stesso

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