2011-12-29 13 views
5

Teniendo en cuenta este código HTML:cómo seleccionar un elemento que NO tiene un enlace dentro de él?

<ul> 
    <li><a href="/artists/gil_elvgren/activity_stream">Activity Stream</a></li> 
    <li><a href="/artists/gil_elvgren/likes">Likes</a></li> 
    <li>Favorites</li> 
    <li><a href="/artists/gil_elvgren/follows">Follows</a></li> 
    <li><a href="/artists/gil_elvgren/sketchbook_comments">Whiteboard</a></li> 

</ul> 

Quiero inyectar el class="current" en la única línea que no tiene un enlace en su interior.

¿Cómo uso jQuery para encontrar un elemento que NO contiene un elemento secundario?

Respuesta

0
$("li").each(function(){ 
    if($(this).children().length == 0){ 
     //found current.. 
     $(this).addClass("current"); 
    } 
}); 
+0

Esto solo funcionará si el 'li' no tiene ningún elemento secundario. Quiero decir, el OP solo quería aquellos que no tienen un hijo 'a'. – kapa

-1

Yo sugeriría que se acaba de añadir un elemento <span> interior de su <li> para diferenciarlo entre los elementos que tienen enlaces en ellos.

<ul> 
    <li><a href="/artists/gil_elvgren/activity_stream">Activity Stream</a></li> 
    <li><a href="/artists/gil_elvgren/likes">Likes</a></li> 
    <li><span>Favorites</span></li> 
    <li><a href="/artists/gil_elvgren/follows">Follows</a></li> 
    <li><a href="/artists/gil_elvgren/sketchbook_comments">Whiteboard</a></li> 
</ul> 

CSS:

ul li a { /* Link CSS */ } 
ul li span { /* Current CSS */ } 
+3

Si él pudiera hacer eso, ¿por qué no simplemente agregar la clase allí? – box86rowh

+0

Esta respuesta no resuelve el problema. – Krule

7

Seleccionar <li> elemento que no tiene hijos <a> utilizando el selector de :has y :not:

$("li:not(:has(a))").addClass("current"); 

jsFiddle

- EDITAR -

Si bien esta podría ser la solución más corta, la legibilidad aparte, definitivamente no es la mejor en cuanto a velocidad.

Teniendo esto en cuenta, le sugiero que compruebe una gran answer proporcionada por @bazmegakapa.

Dado que esto es algo que (o cualquier otra persona incluida yo) podría terminar usando más de una vez, he ampliado jQuery un poco con este plugin/método que puede utilizar con el fin de DRY su código:

jQuery.fn.thatHasNo = function(element, method) { 
    if (typeof method === "undefined" || method === null) method = "children"; 
    return this.not(function() { 
    return $(this)[method](element).length; 
    }); 
}; 

que se puede llamar con:

$("li").thatHasNo("a").addClass("current"); 

Esta extensión, por defecto (si segundo argumento de método no se pasa), comprobar si hay descendientes directos (children) que el selector partido proporcionada. Sin embargo, puede proporcionar cualquier tree-traversal parameter como segundo argumento al método. Por lo tanto, esto puede escribirse como una de las siguientes:

$("li").thatHasNo("a", "children").addClass("current"); 
//... 
$("li").thatHasNo("a", "find").addClass("current"); 
//... 
$("li").thatHasNo(".class", "siblings").addClass("lame"); 

He actualizado para reflejar que jsFiddle.

+0

He agregado algunas notas sobre estos selectores (': has()' y ': not') en mi respuesta. – kapa

+0

+1 Gran complemento :). ¿Puedo sugerir 'typeof method == 'undefined'' en lugar de' method == null'? – kapa

+0

Puede agregar eso, pero ya que es un argumento y por definición ya está definido, no hay necesidad de verificar indefinido :) – Krule

1

Debe utilizar el método .not() (que es básicamente un .filter() negado) con una función de filtro.

$('li') /* select the elements you want to test */ 
    .not(function() { /* run a filter function on them */ 
     /* those that have a direct children link (use find() if you need 
     any kind of children) will return true thus excluded */ 
     return $(this).children('a').length; 
    }) 
    .addClass('current'); /* add our beloved class */ 

jsFiddle Demo


También es posible usar selectores complicados, como @Krule suggested, pero me resulta menos legible e incluso el jQuery manual on :not() advierte contra ella:

El .no() método terminará proporcionándole selecciones más legibles de que empujando selectores o variables complejos en un: not() sele filtro ctor En la mayoría de los casos, es una mejor opción.

Además, :has() no es muy recomendable, así:

Porque: tiene() es una extensión de jQuery y no forma parte de la especificación CSS , consultas usando: tiene() no puede tomar ventaja de el aumento de rendimiento proporcionado por el método DOM querySelectorAll() nativo. Para un mejor rendimiento en navegadores modernos, use $ ("su-pure-css-selector") en su lugar (selector/DOMElement).

+0

He agregado una nota que apunta a su respuesta y la amplié un poco al extender jQuery con el método 'thatHasNo'. – Krule

Cuestiones relacionadas