document.matchesSelector 相当の機能を実装してみた

より効率的なコードに差し替えました

http://dev.w3.org/2006/webapi/selectors-api2/#matchesselectorid:javascripter さんの記事

Selectors APIのmatchesSelectorと、動的なページでのイベント処理

via http://d.hatena.ne.jp/javascripter/20091018/1255889085

を参考に uu.match(expr, ctx, rtype = 0) な関数を書いてみました。

// uu.match - document.matchesSelector like function
function uumatch(expr,    // @param String: "css > expr"
                 ctx,     // @param NodeArray/Node: match context
                 rtype) { // @param Number(= 0): result type,
                          //             0 is Boolean result, matches all,
                          //             1 is Boolean result, matches any,
                          //             2 is NodeArray result, matches array
                          // @return Boolean/NodeArray:
  ctx = ctx.nodeType ? [ctx] : ctx;
  var rv = [], hash = {}, v, w, i = 0, j = 0, ary = uuquery(expr, doc);

  if (ctx.length === 1) {
    v = ctx[0];
    while ( (w = ary[i++]) ) {
      if (v === w) {
        rv.push(v);
        break;
      }
    }
  } else {
    while ( (v = ary[i++]) ) {
      hash[v.uuguid || uunodeid(v)] = 1;
    }
    while ( (v = ctx[j++]) ) {
      (v.uuguid || uunodeid(v)) in hash && rv.push(v);
    }
  }
  return !rtype ? rv.length === ctx.length : rtype < 2 ? !!rv.length : rv;
}

マッチする要素の一覧が欲しい場合は、第三引数(rtype) に 2 を指定します。

デモ

http://pigs.sourceforge.jp/blog/20091229/

リンク(example) をクリックすると、uu.match("p > a", evt.src) でイベントソースが(<a>)かどうかを判定します。

<!doctype html><html><head><meta charset="utf-8" />
<title></title>
<script src="uu.js"></script>
<script src="uu.query.js"></script>
<script>
function xboot(uu) {
/*
  document.addEventListener("click", function(event) {
    if (!event.target.webkitMatchesSelector("p > a")) {
      return;
    }
    confirm("jump?") || event.preventDefault();
  }, false);
 */
  uu.ev(document, "click", function(evt) {
    if (!uu.match("p > a", evt.src)) {
      return;
    }
    confirm("jump?") || uu.ev.stop(evt);
  });
}
</script>
</head>
<body>
  <p>hello <a href="http://example.com/">example</a></p>
<pre>
function xboot(uu) {
/*
  document.addEventListener("click", function(event) {
    if (!event.target.webkitMatchesSelector("p &gt; a")) {
      return;
    }
    confirm("jump?") || event.preventDefault();
  }, false);
 */
  uu.ev(document, "click", function(evt) {
    if (!uu.match("p &gt; a", evt.src)) {
      return;
    }
    confirm("jump?") || uu.ev.stop(evt);
  });
}
</pre>
</body>
</html>


問題が無ければ次回のリリースから利用可能になります。