jQuery выбирает потомков, включая родителя

Рассмотрим следующий HTML:

<div class="foo" id="obj">
   I should be changed red
   <div class="bar" style="color:black;">
      I should not be changed red.
      <div class="foo">I should be changed red.</div>
   </div>
</div>

Учитывая элемент DOM objи выражение, как мне выбрать детей и, возможно obj,? Я ищу что-то похожее на «выбрать потомков», но также включая родителя, если это соответствует выражению.

var obj = $("#obj")[0];

//wrong, may include siblings of 'obj'
$(".foo", $(obj).parent()).css("color", "red");

//wrong -- excludes 'obj'
$(".foo", obj).css("color", "red");

//correct way, but it's annoying
var matches = $(".foo", obj);
if ($(obj).is(".foo")) matches = matches.add(obj);
matches.css("color", "red");

Есть ли более элегантное решение для этого?

13.12.2008 03:49:07
+1: отличный вопрос. Просто попал в эту ситуацию сегодня. Приняли ответ Эндрю и ваш комментарий и добавили тривиальное findAndSelfрасширение jQuery, которое вы предлагали использовать всем. Приветствия.
Gone Coding 5.06.2014 11:03:15
8 ОТВЕТОВ
РЕШЕНИЕ

Если я вас правильно понимаю

$(currentDiv).contents().addBack('.foo').css('color','red');

Я переименовал "div" в "currentDiv" для ясности. При этом выбирается текущий элемент и все содержащиеся в нем элементы, а затем отфильтровываются те, которые не имеют класса, fooи применяется стиль к оставшейся части, т. Е. Те, которые имеют класс foo.

РЕДАКТИРОВАТЬ Небольшая оптимизация

$(currentDiv).find('.foo').addBack('.foo').css('color','red');

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

Этот ответ был обновлен для включения новых методов jQuery. Это было изначально

$(currentDiv).find('.foo').andSelf().filter('.foo').css('color','red');

который все еще требуется для jQuery старше 1.8

28
5.09.2014 13:13:47
Ах, спасибо ... "andSelf ()" - это то, чего мне не хватало. К сожалению, этот метод неэффективен ... все дети и найдены, а затем все просматриваются для фильтрации, а не только один проход.
Sam 13.12.2008 04:07:35
Это все еще немного менее эффективно, чем addback(JQ 1.8 и далее), так как это запускается во filterвторой раз для потомков, даже если они все уже совпадают.
Gone Coding 5.06.2014 10:33:27
Note: This function has been deprecated and is now an alias for .addBack(), which should be used with jQuery 1.8 and later
dsdsdsdsd 5.09.2014 07:00:45
 $('div.foo, div.foo > *').css('color','red');

Основная идея заключается в том, что вы можете разделять различные правила, чтобы они соответствовали запятым. Прямо как в css. Насколько я знаю, все здесь поддерживается jquery и может быть "ORed" через запятую.

-1
13.12.2008 04:02:59
Это выделит все .foo в документе и всех потомков .foo
Sam 13.12.2008 03:58:11
Правильно ... Я думал, это то, что вы имели в виду.
rz. 13.12.2008 03:59:53
Ааа, извините, я уточнил вопрос.
Sam 13.12.2008 04:01:49
Хорошо, теперь ответ: все div класса foo и все их дети. Удовлетворительно?
rz. 13.12.2008 04:03:47
Ответ «все дети [некоторого объекта], которые соответствуют [выражению], а также [некоторому объекту], если он соответствует [выражению]»
Sam 13.12.2008 04:05:44

За исключением более приятного решения, я создал новую функцию и использую ее вместо $:

var _$ = function(expr, parent){ 
   return $(parent).is(expr) ? $(expr, parent).add(parent) : $(expr, parent); 
}
1
13.12.2008 03:55:07
Я думаю, что я просто буду использовать это и расширять jQuery, чтобы сделать его "findAndSelf ()" или что-то в этом роде.
Sam 13.12.2008 04:12:03
findAndSelfВместо этого вы применили ваше предложение (доброе имя) к ответу Эндрю и разместили его для всех, кого можно вырезать и вставить.
Gone Coding 5.06.2014 10:57:55

Разве это не делает то, что вы хотите (если я не понимаю ...)

$(document).ready(function(){
    $("div.foo").css("color", "red");
});
-1
13.12.2008 04:00:22
Это будет «работать», но только потому, что все они оказались divsв примере . Вопрос заключался в том, как включить начальный элемент (если он совпадает) вместе с любыми потомками (которые также совпадают). Что, если бы было больше .foos снаружи #obj? Они также будут включены (что не является желаемым поведением).
Gone Coding 5.06.2014 10:27:45

Если я не ошибаюсь, не могли бы вы сделать следующее?

$("#obj").css("color", "red").find(".foo").css("color", "red");

Найти предполагаемый объект / элемент с помощью CSS, затем найти все объекты / элементы в указанном объекте / элементе с помощью указанного селектора, а затем применить CSS также?

0
5.06.2014 10:07:31
Нет. Они хотят, чтобы родительский элемент был выбран, если он также есть.foo , но ваш просто включает его.
Gone Coding 5.06.2014 10:24:22

В jQuery 1.8 появился метод .addBack () , который принимает селектор в пользу .andSelf (). Таким образом, код tvanfosson становится намного более эффективным, чем

$(currentDiv).find(".foo").addBack(".foo").css("color", "red");

Если у вас этого не было, я думаю, что

$(currentDiv).find(".foo").add(currentDiv.filter(".foo")).css("color", "red");

было бы довольно эффективно, если не очень красиво.

9
31.05.2013 23:39:27
Определенно предпочтение от jQuery 1.8. Добавили ваше предложение в качестве findAndSelfметода расширения jQuery ниже. Получилось очень чистое использование addBack, полный кредит для вас . Ура :)
Gone Coding 5.06.2014 11:01:02

Ответ Эндрю был настолько полезным и самым эффективным из всех ответов (начиная с jQuery 1.8 и далее), поэтому я сделал так, как предложил Сэм, и превратил его в тривиальный метод расширения jQuery для всех:

Код расширения:

jQuery.fn.findAndSelf = function (selector){
    return this.find(selector).addBack(selector);
};

используйте как это:

$(function(){
    $('#obj').findAndSelf('.foo').css('color', 'red');
});

JSFiddle: http://jsfiddle.net/BfEwK/

Полная благодарность Андрею за предложение addBack()как лучший вариант (на данный момент). За него проголосовали соответственно и предложили всем сделать то же самое.

2
23.05.2017 10:29:43
Как никто, казалось бы, не заметил этого. Вы заслуживаете объятия и высокого пять.
The Dembinski 27.10.2016 18:13:20
@TheDembinski: Hug принят с благодарностью (однако я не делаю высокие 5) :)
Gone Coding 28.10.2016 09:21:33

Более короткий способ выбрать все элементы-потомки, включая родительский элемент:

$('*', '#parent').addBack();

Который так же, как:

$('#parent').find('*').addBack();

Конечно, вы можете изменить универсальный селектор на нужный элемент.

$('.foo', '#parent').addBack();

или

$('#parent').find('.foo').addBack();
0
10.12.2015 19:13:00