現在のノードを含むjQuery find(..)メソッドを探しています


134

jQuery find(..)トラバーサルメソッドには現在のノードが含まれていません。現在のノードの子から始まります。マッチングアルゴリズムに現在のノードを含む検索操作を呼び出す最善の方法は何ですか?ドキュメントを調べても、すぐには何も飛び出しません。

回答:


153

jQuery 1.8以降では、を使用できます.addBack()。それはセレクターを取るので、結果をフィルターする必要はありません:

object.find('selector').addBack('selector')

jQuery 1.8より前は、 .andSelf()、(現在は非推奨で削除されている)で、フィルタリングが必要でした。

object.find('selector').andSelf().filter('selector')

5
これをbowerに登録されたプラグインjquery.findIncludeSelfとしてバンドルしました。参照github.com/ronen/jquery.findIncludeSelf
Ronen氏

18
@ronen 1行で実行できる何かのための追加ファイル?ありがとう、でも結構です。

6
@ prc322とにかく、すべてのJavaScriptを単一のファイルにバンドルするデプロイメントでは、余分なファイルが邪魔になりません。一般的に、私は、コードを読みにくく、バグが発生する可能性が高いもので乱雑にするよりも、単純なものでも(テストされた)ライブラリメソッドを使用することを好みます。特にこの場合、'selector'2回指定する必要があるIMHO は、カプセル化をさらに望ましいものにします。YMMV
ronen

わかりましたので、私は分厚いかもしれませんが'selector'、(@ ronenによって言及されているように)2回指定する必要がないので、単に使用できませんでしたobject.parent().find('selector')か??? —私はあなたのためにそれをするlibのアイデアが好きだと言われています。
サム・

8
@ circa1983にobject.parent().find('selector')は、の兄弟objectとその子孫が含まれます。
Robert

41

これを直接行うことはできません。私が考えることができる最も近いのは、次のようにを使用.andSelf()して呼び出す.filter()ことです。

$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);

残念ながら.andSelf()、セレクターはありません。これは便利です。


7
この質問に答えた直後に、jqueryページにコメントを追加しましたapi.jquery.com/andSelf/#comment-50124533これで、完全です。いいね!私はデューデリジェンスを行い、それも「気に入りました」。
John K

2
2番目のものは、驚くほど遅いでしょう。最初は単に遅いだけです。
Tgr

@Tgr-異論はありませんが、非常に多数の要素を扱っている場合を除いて、最初のものはそのショーであってはなりません。チェーンする必要がない場合は、これらの要素の再フィルタリングを確実にスキップできます。
Nick Craver

3
興味深いことに、closest(..)現在のDOM要素と上位のツリーが含まれていますが、ツリーの下位にあるすべてのトラバーサルメソッドfind(..)は現在の要素と一致しません。完全な垂直検索で両方の操作を一緒に使用した場合、jQueryチームが意図的にこれらを重複なしに実装したかのようです。
John K

17
.andSelf()はv1.8で非推奨になり、引数としてセレクターを受け取る.addBack()に置き換えられたことに注意してください。参照api.jquery.com/addBack
kkara

9

定義する

$.fn.findSelf = function(selector) {
    var result = this.find(selector);
    this.each(function() {
        if ($(this).is(selector)) {
            result.add($(this));
        }
    });
    return result;
};

次に使用します

$.findSelf(selector);

の代わりに

$find(selector);

残念ながら、jQueryにはこの機能が組み込まれていません。何年もの開発の間、本当に奇妙です。.find()の動作方法が原因で、私のAJAXハンドラーが一部の上位要素に適用されませんでした。


これはバギーです。それらの1つだけが一致する場合でも、すべての「自己」を追加します...-このバグの1つの理由は、気まぐれな名前のjQueryメソッドです...
Robert Siemer

あなたが報告したバグを修正しようとしました。今は正常に動作しますか?
Dmitriy Sintsov

他のほとんどの回答はfilter()そこで使用されます。
Robert Siemer

5
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))

$('selector')スピードアップのために変数に保存できます。必要な場合は、このためのカスタム関数を作成することもできます。

$.fn.andFind = function(expr) {
  return this.find(expr).add(this.filter(expr));
};

$('selector').andFind('otherSelector')

ただし、これはセレクターから始めた場合にのみ機能しますが、そうでない場合もあります。また、それは正しくありません。それは$('selector').find('otherSelector').add($('otherSelector'))、あなたが今持っているものはと同等.andSelf()です。最後に、.andFind()は式に基づいてフィルタリングしないため、次のようにする必要があります。.add($(this).filter(expr)):)
Nick Craver

@Nick Craver:ええ、フィルタリング部分を忘れてしまいました。$('selector')jQueryオブジェクトを取得する他のメソッドで置き換えても(それがセレクターで始まらないことによって意図したものである場合)、実際に問題なくadd()処理$()できます。
Tgr

私のポイントは、あなたの$('selector')かもしれ$('selector').children('filter').closest('.class').last()ないということでした...それはチェーンにあるかもしれません、そしてあなたが追加しているそのオブジェクトが何であるかわからないので、一般的な解決策はフィルターがするように前のオブジェクトを取るべきです:)
Nick Craver

それがなぜ問題になるのか、まだわかりません。thisプラグインが呼び出されたjQueryオブジェクトです。呼び出しチェーンの結果である可能性もあります。
Tgr

5

受け入れられた回答は非常に非効率的であり、すでに一致している要素のセットをフィルターに掛けます。

//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);

3

チェーンが適切に機能するようにしたい場合は、以下のスニペットを使用してください。

$.fn.findBack = function(expr) {
    var r = this.find(expr);
    if (this.is(expr)) r = r.add(this);
    return this.pushStack(r);
};

end関数の呼び出し後、#foo要素を返します。

$('#foo')
    .findBack('.red')
        .css('color', 'red')
    .end()
    .removeAttr('id');

追加のプラグインを定義しないと、これに悩まされます。

$('#foo')
    .find('.red')
        .addBack('.red')
            .css('color', 'red')
        .end()
    .end()
    .removeAttr('id');

ああ、いいえ...のthisいずれthis.is()か1つだけが一致する場合、複数の要素がすでに満たされている場合。
Robert Siemer

3

場合は、あなたが探している正確に一つの要素、現在の要素またはその内部のいずれかを、あなたが使用することができます。

result = elem.is(selector) ? elem : elem.find(selector);

あなたが使用できる複数の要素を探している場合には:

result = elem.filter(selector).add(elem.find(selector));

andSelf/ の使用andBackはかなりまれですが、理由はわかりません。おそらく、私の前に述べたパフォーマンスの問題が原因です。

(私は今、Tgrがすでにその2番目のソリューションを提供していることに気づきました)


2

これは古い質問であることはわかっていますが、もっと正しい方法があります。順序が重要な場合、たとえばのようなセレクターを一致させる:first場合、find()実際の要素のセットが実際に含まれている場合とまったく同じ結果を返す小さな関数を作成しました。

$.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);
};

それは決して効率的ではありませんが、適切な順序を維持するために私が考え出した最高の方法です。


1

andSelfはあなたが望むものだと思います:

obj.find(selector).andSelf()

これは、セレクターと一致するかどうかにかかわらず、常に現在のノードを追加することに注意してください。



0

繰り返さない解決策を見つけようとしていたない(つまり、同じセレクターを2回入力。

そして、この小さなjQuery拡張はそれを行います:

jQuery.fn.findWithSelf = function(...args) {
  return this.pushStack(this.find(...args).add(this.filter(...args)));
};

これはfind()(子孫のみ)とfilter()(現在のセットのみ)を組み合わせ、両方の引数をサポートします。pushStack()することができます.end()期待どおりに動作します。

このように使用します:

$(element).findWithSelf('.target')

-2

これが正しい(悲しい)真実です。

$(selector).parent().find(oSelector).filter($(selector).find('*'))

http://jsfiddle.net/SergeJcqmn/MeQb8/2/


ただし、切り離されたノード(およびドキュメント自体)では機能しません。
John Dvorak

2
ええと、いいえ、これは$(selector)すべての場合にそれ自体をセットから削除します。
John Dvorak
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.