2013-03-10 21 views
14

jQuery.closest()のDOM APIで同等の作業をしている人はいますか?ネイティブDOMを使用する最も近い祖先一致セレクタ?

Selectors Level 2 draftのように見えます。jQuery.is()に相当するmatches()が追加されています。したがって、ネイティブの最も近い文字は、はるかに書きやすくなります。セレクタにclosest()を追加していますか?

function closest(elem, selector) { 
    while (elem) { 
     if (elem.matches(selector)) { 
      return elem; 
     } else { 
      elem = elem.parentElement; 
     } 
    } 
    return null; 
} 

トラブルがあり、matches機能が適切にサポートされていません:それは広く、まだサポートされていないものの

+0

すべてのブラウザがこの方法を実装している場合のみ、「簡単に」できます。:-(これはとにかく書かれていなければなりません、私は 'macthes'フォークのための機能の検出と思います。それは難しくはありませんが、少し遅いでしょう – RobG

+0

ええ、[近代化の例があります] /modernizr.com/docs/#prefixeddom)のベンダー接頭辞 'matchesSelector'に戻っています。 – hurrymaplelad

答えて

3

Element.closest()

its support

は)パフォーマンスの面で最適ではないようで、原因が明らかに(一致する)querySelectorAll(への呼び出しを行います)たびに親をテストし、ジョブに対して1回の呼び出しで十分です。

MDNのclosest()のpolyfillは次のとおりです。 querySelectorAll()

if (window.Element && !Element.prototype.closest) { 
    Element.prototype.closest = 
    function(s) { 
     var matches = (this.document || this.ownerDocument).querySelectorAll(s), 
      i, 
      el = this; 
     do { 
      i = matches.length; 
      while (--i >= 0 && matches.item(i) !== el) {}; 
     } while ((i < 0) && (el = el.parentElement)); 
     return el; 
    }; 
} 

への単一の呼び出しに注意してくださいしかし、アタッチされていない木の上で正しく動作しません。このように実現される機能を心に留め)(

//Element.prototype.closestTest = function(s){...as seen above...}; 

var detachedRoot = document.createElement("footer"); 
var child = detachedRoot.appendChild(document.createElement("div")); 
detachedRoot.parentElement; //null 

child.closestTest("footer"); //null 

document.documentElement.append(detachedRoot); 
child.closestTest("footer"); //<footer> 

最も近いものの(はdocument.firstChildルートから外します) Firefox 51.0.1に実装されているのは、分離したツリーでうまく動作しているようです。

document.documentElement.removeChild(detachedRoot); 
child.closestTest("footer"); //null 
child.closest("footer"); //<footer> 
+0

MDNによれば、もう「実験的」ではないようです:https://developer.mozilla.org/en-US/docs/Web/API/Element/closest – Xenos

3

これは、それがmatches機能を考えると、非常に簡単であるべきように聞こえます。比較的新しいAPIなので、ChromeとSafariではwebkitMatchesSelector、FirefoxではmozMatchesSelectorとして利用できます。

+0

「* MatchesSelector'で、ネイティブDOMだけを使用して最も近いものを整理するのは簡単です。要素のネイティブメソッドとして 'element.closest(selector)'を追加してください。 – hurrymaplelad

+0

@hurrymaplel W3Cに参加して提案する必要があるでしょう。コードの上に) – Alnitak

33

アルニタクの解答から外れています。 DOM仕様のmatchesになったmatchesSelectorの現在の実装を以下に示します。

// get nearest parent element matching selector 
function closest(el, selector) { 
    var matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector; 

    while (el) { 
     if (matchesSelector.call(el, selector)) { 
      break; 
     } 
     el = el.parentElement; 
    } 
    return el; 
} 

ブラウザのサポートは素晴らしいです:http://caniuse.com/matchesselector

+0

私は引き裂かれています。実装に感謝しますが、それはネイティブが近づいていないことを意味しますか? – hurrymaplelad

+1

'.call(ctx、arg)'ではなく '.bind(ctx)(arg)前者は新しい実行コンテキストを作成し、後者は実行コンテキストを作成しません。 – Alnitak

+1

'call(elem、selector)'は 'bind(elem)(selector)'よりも優れたパフォーマンスを示し、ベンチマークhttp://jsperf.com/native-vs-jquery-closestです。まだ簡単な '.parentNode.parentNode'メソッドは非常に高速です。 – Binyamin

11

はクローム40のように思えるネイティブelement.closest()方法(http://blog.chromium.org/2014/12/chrome-40-beta-powerful-offline-and.html)をもたらすここで指定:element.closestを使用してhttps://dom.spec.whatwg.org/#dom-element-closest

+2

'element.closest'はChromeではなく40になりました(https://crbug.com/422731#c7を参照)。また、[Firefox 35](https://developer.mozilla.org/en-US/Firefox/Releases/35)にも入っています –

+0

polyfillを使用して、古いブラウザ(たとえば、https: //github.com/jonathantneal/closest – user1613797

1

()私たちは、最も近い祖先のマッチングを見つけることができますセレクタ。このメソッドは、セレクタリストをパラメータとして受け取り、最も近い祖先を返します。ロブのコメントあたりのように、このAPIは

としては、WHATWG仕様で説明した35クローム41とFFから利用できるようになりますhttps://dom.spec.whatwg.org/#dom-element-closest

例:HTML、以下の警告メッセージが表示されます「真」

<html> 
    <body> 
     <foo> 
      <bar> 
       <a id="a"> 
        <b id="b"> 
         <c id="c"></c> 
        </b> 
       </a> 
      </bar> 
     </foo> 
    <script> 
     var a = document.getElementById('a'); 
     var b = document.getElementById('b'); 
     var c = document.getElementById('c'); 
     alert(c.closest("a, b")==b); 
    </script> 
    </body> 
</html> 
1

Aほとんど再帰はそのトリックを行います。

Element.matches(このような機能を実装
// get nearest parent element matching selector 
var closest = (function() { 
    var matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector; 

    return function closest(el, selector) { 
     return !el ? null : 
     matchesSelector.call(el, selector) ? el : closest(el.parentElement, selector); 
    }; 
})(); 
+0

または単にreturn element.tagName === 'HTML'? null:element.matches(セレクタ)?要素:nearest(element.parentNode、selector); ';) – yckart

+0

@yckartが更新されました。 –

関連する問題