Respostas:
Para o jQuery 1.8 e superior, você pode usar .addBack()
. É preciso um seletor para que você não precise filtrar o resultado:
object.find('selector').addBack('selector')
Antes do jQuery 1.8, você estava preso .andSelf()
(agora obsoleto e removido), que precisava de filtragem:
object.find('selector').andSelf().filter('selector')
'selector'
duas vezes torna o encapsulamento extra desejável. YMMV
'selector'
duas vezes (como mencionado por @ronen), você não poderia simplesmente usar object.parent().find('selector')
??? - Dito isto, gosto da idéia de uma biblioteca que faz isso por você.
object.parent().find('selector')
inclui irmãos object
e seus descendentes.
Você não pode fazer isso diretamente, o mais próximo que consigo pensar é usar .andSelf()
e chamar .filter()
, assim:
$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);
Infelizmente .andSelf()
não é necessário um seletor, o que seria útil.
closest(..)
inclui o elemento DOM atual e a árvore, enquanto todos os métodos transversais de árvore, como find(..)
etc, não correspondem ao elemento atual. É como se a equipe do jQuery os tivesse implementado propositalmente, sem sobreposição quando as duas operações foram usadas juntas para uma pesquisa vertical completa.
Definir
$.fn.findSelf = function(selector) {
var result = this.find(selector);
this.each(function() {
if ($(this).is(selector)) {
result.add($(this));
}
});
return result;
};
então use
$.findSelf(selector);
ao invés de
$find(selector);
Infelizmente, o jQuery não possui esse recurso. Realmente estranho por tantos anos de desenvolvimento. Meus manipuladores AJAX não foram aplicados a alguns dos principais elementos devido a como o .find () funciona.
filter()
lá, o que faz mais sentido.
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))
Você pode armazenar $('selector')
em uma variável para acelerar. Você pode até escrever uma função personalizada para isso, se precisar muito:
$.fn.andFind = function(expr) {
return this.find(expr).add(this.filter(expr));
};
$('selector').andFind('otherSelector')
$('selector').find('otherSelector').add($('otherSelector'))
que você tem agora é equivalente .andSelf()
. Por fim, o .andFind()
filtro não é baseado na expressão, você precisaria .add($(this).filter(expr))
:) :)
$('selector')
foi substituído por algum outro método de obter um objeto jQuery (se é isso que você quis dizer com não iniciar com um seletor), ele add()
pode lidar com tudo da mesma maneira que $()
pode.
$('selector')
pode estar $('selector').children('filter').closest('.class').last()
... pode estar em cadeia e você não tem idéia do que está adicionando, então a solução genérica deve pegar o objeto anterior como o filtro :)
this
é qualquer objeto jQuery em que um plug-in foi chamado. Poderia ser o resultado de uma cadeia de chamadas.
A resposta aceita é muito ineficiente e filtra o conjunto de elementos que já correspondem.
//find descendants that match the selector
var $selection = $context.find(selector);
//filter the parent/context based on the selector and add it
$selection = $selection.add($context.filter(selector);
Se você deseja que o encadeamento funcione corretamente, use o trecho abaixo.
$.fn.findBack = function(expr) {
var r = this.find(expr);
if (this.is(expr)) r = r.add(this);
return this.pushStack(r);
};
Após a chamada da função final, ele retorna o elemento #foo.
$('#foo')
.findBack('.red')
.css('color', 'red')
.end()
.removeAttr('id');
Sem definir plugins extras, você está preso a isso.
$('#foo')
.find('.red')
.addBack('.red')
.css('color', 'red')
.end()
.end()
.removeAttr('id');
this
mais de um elemento this.is()
já estiver satisfeito, se apenas um deles corresponder.
Caso esteja procurando exatamente um elemento , o atual ou o outro, pode usar:
result = elem.is(selector) ? elem : elem.find(selector);
Caso esteja procurando por vários elementos, você pode usar:
result = elem.filter(selector).add(elem.find(selector));
O uso de andSelf
/andBack
é bastante raro, não sei por quê. Talvez por causa dos problemas de desempenho que alguns caras mencionaram antes de mim.
(Agora notei que o Tgr já deu essa segunda solução)
Sei que essa é uma pergunta antiga, mas existe uma maneira mais correta. Se a ordem é importante, por exemplo, quando você está combinando um seletor como :first
, escrevi uma pequena função que retornará exatamente o mesmo resultado como se find()
realmente incluísse o conjunto atual de elementos:
$.fn.findAll = function(selector) {
var $result = $();
for(var i = 0; i < this.length; i++) {
$result = $result.add(this.eq(i).filter(selector));
$result = $result.add(this.eq(i).find(selector));
}
return $result.filter(selector);
};
Não será eficiente de forma alguma, mas é o melhor que eu tenho para manter a ordem correta.
Se você está olhando estritamente nos nós atuais, simplesmente faz
$(html).filter('selector')
Eu estava tentando encontrar uma solução que não se repita (ou seja, não insere o mesmo seletor duas vezes).
E essa pequena extensão jQuery faz isso:
jQuery.fn.findWithSelf = function(...args) {
return this.pushStack(this.find(...args).add(this.filter(...args)));
};
Ele combina find()
(apenas descendentes) com filter()
(apenas o conjunto atual) e suporta os argumentos que ambos comem. O pushStack()
permite.end()
trabalhar como esperado.
Use assim:
$(element).findWithSelf('.target')
Aqui está a verdade certa (mas triste):
$(selector).parent().find(oSelector).filter($(selector).find('*'))
$(selector)
do conjunto em todos os casos.