jqueryデータセレクター


184

要素の.data()オブジェクトに格納されている値に基づいて要素を選択する必要があります。少なくとも、次のように、セレクターを使用して最上位のデータプロパティを選択したいと思います。

$('a').data("category","music");
$('a:data(category=music)');

または、セレクターは通常の属性セレクター形式になります。

$('a[category=music]');

または属性形式ですが、次の場所にあることを示す指定子があります.data()

$('a[:category=music]');

James Padolseyの実装はシンプルでありながら見栄えが良いことがわかりました。セレクタは、そのページに示されているミラーメソッドの上でフォーマットします。このシズルパッチもあります。

何らかの理由で、jQuery 1.4にはjquery .data()オブジェクトの値のセレクターのサポートが含まれることをしばらく読んだことを思い出しました。しかし、今探しているので見つけられません。多分それは私が見た機能要求だけだった。これに対するサポートはありますか?私はそれを見ていませんか?

理想的には、ドット表記を使用してdata()のサブプロパティをサポートしたいと思います。このような:

$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a[:user.name.first=Tom]');

また、指定されたすべてのデータセレクターを持つ要素のみが検出される複数のデータセレクターもサポートしたいと考えています。通常のjquery複数セレクターはOR演算を行います。たとえば、クラスまたは)のいずれかのタグを$('a.big, a.small')選択しaます。私はANDを探しています、おそらくこのように:bigsmall

$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');

最後に、比較演算子と正規表現機能がデータセレクターで利用できると便利です。だから$(a[:artist.id>5000])可能でしょう。私はおそらくこれを使って多くのことを行うことができると思いますfilter()が、単純なセレクターフォーマットがあればいいでしょう。

これを行うにはどのようなソリューションがありますか?現時点で、ジェームズパドルシーは最高のソリューションですか?私の懸念は主にパフォーマンスに関するものですが、サブプロパティのドット表記や複数のデータセレクターなどの追加機能にも関係しています。これらのものをサポートする、または何らかの点で優れている実装は他にありますか?


jquery uiコアを使用するapi.jqueryui.com/category/ui-core これには:data()セレクターがあります
regisbsb

回答:


101

dataネストされたクエリとAND条件を実行できるようにする新しいセレクターを作成しました。使用法:

$('a:data(category==music,artist.name==Madonna)');

パターンは次のとおりです。

:data( {namespace} [{operator} {check}]  )

「演算子」と「チェック」はオプションです。したがって、それしか持って:data(a.b.c)いない場合は、の真実性をチェックするだけですa.b.c

以下のコードで使用可能な演算子を確認できます。それらの中には~=、正規表現テストを可能にするものがあります:

$('a:data(category~=^mus..$,artist.name~=^M.+a$)');

私はいくつかのバリエーションでそれをテストしました、そしてそれはかなりうまくいくようです。私はおそらくこれをGithubリポジトリとして(完全なテストスイートとともに)追加するので、要注意です!

コード:

(function(){

    var matcher = /\s*(?:((?:(?:\\\.|[^.,])+\.?)+)\s*([!~><=]=|[><])\s*("|')?((?:\\\3|.)*?)\3|(.+?))\s*(?:,|$)/g;

    function resolve(element, data) {

        data = data.match(/(?:\\\.|[^.])+(?=\.|$)/g);

        var cur = jQuery.data(element)[data.shift()];

        while (cur && data[0]) {
            cur = cur[data.shift()];
        }

        return cur || undefined;

    }

    jQuery.expr[':'].data = function(el, i, match) {

        matcher.lastIndex = 0;

        var expr = match[3],
            m,
            check, val,
            allMatch = null,
            foundMatch = false;

        while (m = matcher.exec(expr)) {

            check = m[4];
            val = resolve(el, m[1] || m[5]);

            switch (m[2]) {
                case '==': foundMatch = val == check; break;
                case '!=': foundMatch = val != check; break;
                case '<=': foundMatch = val <= check; break;
                case '>=': foundMatch = val >= check; break;
                case '~=': foundMatch = RegExp(check).test(val); break;
                case '>': foundMatch = val > check; break;
                case '<': foundMatch = val < check; break;
                default: if (m[5]) foundMatch = !!val;
            }

            allMatch = allMatch === null ? foundMatch : allMatch && foundMatch;

        }

        return allMatch;

    };

}());

@JP:とても甘い、私はあなたに頼ることができると知っていました!もう寝るつもりですが、明日やってみます。OR演算も可能ですか?私はそれを必要としません、好奇心が強いだけです。
Tauren、

1
@JP:また、他のデータセレクターソリューションについてのあなたの見方についても興味があります。たとえば、このプラグイン: plugins.jquery.com/project/dataSelector
Tauren、

1
OR演算を実行することは可能ですが、2つのセレクターを用意するのが最善かもしれません$("a:data(condition),a:data(orCondition)")...同じ効果があります。追加する機能が多いほど、速度は遅くなります。ロジックが複雑な場合は、を使用します$(foo).filter(function(){...})
James

3
@JP:これをgithubプロジェクトに変えたことはありますか?jQuery 1.5.1を使用して、html5属性data-test = "500"の入力でセレクター$( "input:data(test> 400)")を使用してテストを実行していますが、セレクターは何も返しません。
ジェームズサウス

1
@JamesSouthこれは、この回答のセレクターjQuery.dataが、HTML5属性で定義されたデータを取得しない低レベルを使用しているためです。その機能が必要な場合は、に変更できますjQuery.data$('selector').data、それは速度とのトレードオフです。
シェフ、2011年

175

現時点では、次のように選択しています。

$('a[data-attribute=true]')

これは問題なく動作するように見えますが、jQueryが 'data-'接頭辞なしでその属性で選択できればよいでしょう。

私は、jQueryを介して要素にデータを動的に追加してこれをテストしていないため、これがこのメソッドの欠点になる可能性があります。


これはまさに私が探していたものです。スウィート
MikeMurko、2011

109
これは、.data()関数を介してJS経由でデータをアタッチ/変更する場合は実際には機能しません。属性セレクターはDOMのみをチェックし、JSは.data()をメモリに保存します
Clarence Liu

1
.data()経由でアタッチする場合、属性でどのようにアクセスするか教えていただけませんか?
Maxim V. Pavlov

1
このスレッドで提供されている他の回答は、非常に単純なユースケース以外のより良い選択肢であることをお勧めします。
アッシュ

Dmitriのソリューションはサードパーティのコードに依存しないため、私には見栄えがします。
アッシュ

83

プラグインなしで簡単なフィルタリング機能を使用することもできます。これはあなたが望むものではありませんが、結果は同じです:

$('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"});

$('a').filter(function() {
    return $(this).data('user') && $(this).data('user').name.first === "Tom";
});

2
これは素晴らしいアイデアです。filterトラバーサル関数がテスト関数を受け入れることができるのを忘れていました=)おかげで
クラレンスリュー

トムと同じではなく、「contains」を実行するにはどうすればよいですか?
Alisso 2013年

1
Alisso、name.first == "Tom"の代わりにname.first && name.first.indexOF( "Tom")> -1;を使用
ドミトリ

24

$('a[data-attribute=true]')data()関数を介してDOM要素にデータを添付した場合、Ashleyの回答に従って機能しないことを警告します。

HTMLに実際のデータ属性を追加した場合は期待どおりに機能しますが、jQueryはデータをメモリに格納するため、得られる結果は$('a[data-attribute=true]')正しくありません。

データプラグインhttp://code.google.com/p/jquerypluginsblog/を使用するfilterか、Dmitriのソリューションを使用するか、すべての要素に対して$ .eachを実行して.data()を繰り返し確認する必要があります


私の場合、サーバー側でフィールドに事前入力していて、初期ロード時にこの方法で調べるだけでよいので、問題ありません。フィルターはおそらく同じくらい高速です(ほぼ確実に低速です)が、これは読みやすさを優先します。
Don

11

これだけを行う:data()フィルタープラグインがあります :)

あなたの質問に基づくいくつかの例:

$('a:data("category=music")')
$('a:data("user.name.first=Tom")');
$('a:data("category=music"):data("artist.name=Madonna")');
//jQuery supports multiple of any selector to restrict further, 
//just chain with no space in-between for this effect

可能なことと比較してパフォーマンスが極端に優れているわけではありません。$._cache対応する要素から選択して取得するのははるかに高速ですが、はるかに多くのラウンドアバウトであり、取得方法に関しては「jQuery-ey」ではありません。もの(通常、要素側から入ります)。頭の中で、一意のIDから要素に移行するプロセス自体がパフォーマンスの点で複雑であるため、これがとにかく最速かどうかはわかりません。

あなたが言及した比較セレクターはで行うのが最善.filter()ですが、プラグインには組み込みのサポートはありませんが、多くの問題なしに追加できます。


完全な答えをありがとう。HTML5 data-*属性を使用してそれらを選択する方が、.data()プロパティを選択するよりも速いかどうか知っていますか?また、$ ._ cacheの詳細はどこで確認できますか?私はそれをグーグルで探しました、しかし多くを見つけていません。
Tauren

@Tauren-私のせいで$.cacheはありません$._cache、jQueryコアでどのように実装および使用されているかをここで確認 でき.data()ます。 in $.cache[elementUniqueID]、これは必要に応じて各要素に段階的に割り当てられるIDです。たとえば、1、2、3などです。その上昇IDは、先日gitコメントに基づいて、jQuery 1.4.3で公開されると思います。HTML 5のルートの方が高速だと思いますが、利用できるブラウザーの最適化によって異なります(さらに多くのものが利用可能になると確信しています)。
Nick Craver

7

あなたは、設定することができますdata-*使用してニレの属性をattr()、およびその属性を使用して選択します。

var elm = $('a').attr('data-test',123); //assign 123 using attr()
elm = $("a[data-test=123]"); //select elm using attribute

そして今、そのニレのために、両方attr()123data()が生成されます:

console.log(elm.attr('data-test')); //123
console.log(elm.data('test')); //123

しかし、あなたがする値を変更する場合は456を使用してattr()data() まだだろう123

elm.attr('data-test',456); //modify to 456
elm = $("a[data-test=456]"); //reselect elm using new 456 attribute

console.log(elm.attr('data-test')); //456
console.log(elm.data('test')); //123

ですから、私が理解しているように、必要がない場合は、コード内の混合attr()data()コマンドを回避する必要があると思われます。なぜなら、その初期値はDOMからのものである可能性がありますが、「メモリ」と相互作用しattr()ますが、DOMと直接対応しているようdata()です。ただし、重要な点は、この2つが必ずしも同期している必要はないということです。

だから注意してください。

とにかくdata-*、DOMやメモリの属性を変更しないのであれば、問題はありません。値の変更を開始するとすぐに、潜在的な問題が発生する可能性があります。

アッシュの答え@に@Clarence劉のおかげだけでなく、このポスト



5

jQueryUIも使用する場合:dataは、データ項目の存在をチェックするセレクターの(単純な)バージョンを取得するため$("div:data(view)")、またはのようなことができます$( this ).closest(":data(view)")

http://api.jqueryui.com/data-selector/を参照してください。彼らがそれをどれほど長く持っていたかはわかりませんが、それは今そこにあります!


これはあなたが言ったようにデータ項目の存在をチェックするだけです。それは値をチェックしません(ドキュメントによると)。ただし、これについて知っておくとよい
Fractalf

3

ここに人生を簡素化するプラグインがありますhttps://github.com/rootical/jQueryDataSelector

そのように使用してください:

data selector           jQuery selector
  $$('name')              $('[data-name]')
  $$('name', 10)          $('[data-name=10]')
  $$('name', false)       $('[data-name=false]')
  $$('name', null)        $('[data-name]')
  $$('name', {})          Syntax error
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.