Как выбрать элемент, который не имеет ссылки внутри него? - PullRequest
6 голосов
/ 30 декабря 2011

Учитывая этот HTML:

<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>

Я хочу добавить class="current" в отдельную позицию, в которой НЕ содержится ссылка.

Как использовать jQuery для поиска элемента, который НЕ содержит дочерний элемент?

Ответы [ 4 ]

8 голосов
/ 30 декабря 2011

Выберите элемент <li>, у которого нет дочернего элемента <a>, с помощью селектора :has и :not:

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

jsFiddle

- РЕДАКТИРОВАТЬ -

Хотя это может быть самое короткое решение, за исключением читабельности, оно определенно не является лучшим в отношении скорости.

Имея это в виду, я бы посоветовал вам проверить отличный ответ , предоставленный @bazmegakapa.

Поскольку это то, что вы (или кто-либо другой, включая меня) могли бы использовать более одного раза, я немного расширил jQuery с помощью этого плагина / метода, который вы можете использовать, чтобы DRY ваш код:

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

По которому можно позвонить:

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

По умолчанию это расширение (если второй аргумент метода не передан) проверит, есть ли прямые потомки ( children ), соответствующие указанному селектору. Однако вы можете указать любой параметр обхода дерева в качестве второго аргумента метода. Таким образом, это можно записать в виде одного из следующих:

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

Я обновил jsFiddle , чтобы отразить это.

1 голос
/ 30 декабря 2011

Вы должны использовать метод .not() (который по сути является отрицательным .filter()) с функцией фильтра.

$('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


Вы также можете использовать сложные селекторы, как @ Круле предложил , но я считаю его менее читабельным, и даже руководство jQuery по: not () предостерегает отit:

Метод .not () в итоге предоставит вам более читаемые выборки, чем вставка сложных селекторов или переменных в фильтр селекторов: not ().В большинстве случаев это лучший выбор.

Кроме того, :has() также не рекомендуется:

Потому что: has () является расширением jQuery и не является частью спецификации CSS, запросы с использованием: has () не могут воспользоваться преимуществами повышения производительности, обеспечиваемыми собственным методом DOM querySelectorAll ().Для повышения производительности в современных браузерах вместо этого используйте $ ("your-pure-css-selector"). Has (selector / DOMElement).

0 голосов
/ 30 декабря 2011

Я бы посоветовал вам просто добавить элемент <span> внутри вашего <li>, чтобы дифференцировать его между элементами, на которых есть ссылки.

<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 */ }
0 голосов
/ 30 декабря 2011
$("li").each(function(){
    if($(this).children().length == 0){
        //found current..
        $(this).addClass("current");
    }
});
...