今回は,jQuery特有のセレクタ式を処理する部分になります。jQuery.filterメソッドについては次回の説明となりますが,そちらも合わせて読んで行くとより理解しやすいかと思います。
jQuery.expr
1360行目からは,セレクタ式のための正規表現を定義する部分です。
具体的な説明に入る前に,まずソースコード中に登場するm[2]とm[3]が何を表すのかを説明しておきましょう。mは1658行目にて定義されていて,jQuery.parseの正規表現にマッチした結果が格納されます。また,aには対象となる要素が格納されます。
1364行目からは,":"以降に続くフィルタの定義になります。細かな部分はjQueryドキュメントのAPI/1.2/Selectorsの部分を読んで頂ければ理解できると思うので,ここではいくつかの重要な箇所に絞って説明していきます。
1360: jQuery.extend({
1361: expr: {
1362: "": "m[2]=='*'||jQuery.nodeName(a,m[2])",
1363: "#": "a.getAttribute('id')==m[2]",
1364: ":": {
1365: // Position Checks
1366: lt: "i<m[3]-0",
1367: gt: "i>m[3]-0",
1368: nth: "m[3]-0==i",
1369: eq: "m[3]-0==i",
1370: first: "i==0",
1371: last: "i==r.length-1",
1372: even: "i%2==0",
1373: odd: "i%2",
1374:
1375: // Child Checks
1376: "first-child": "a.parentNode.getElementsByTagName('*')[0]==a",
1377: "last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a",
1378: "only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')",
1379:
1380: // Parent Checks
1381: parent: "a.firstChild",
1382: empty: "!a.firstChild",
1383:
1384: // Text Check
1385: contains: "(a.textContent||a.innerText||jQuery(a).text()||'').indexOf(m[3])>=0",
1386:
1387: // Visibility
1388: visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
1389: hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"',
1390:
1391: // Form attributes
1392: enabled: "!a.disabled",
1393: disabled: "a.disabled",
1394: checked: "a.checked",
1395: selected: "a.selected||jQuery.attr(a,'selected')",
1396:
1397: // Form elements
1398: text: "'text'==a.type",
1399: radio: "'radio'==a.type",
1400: checkbox: "'checkbox'==a.type",
1401: file: "'file'==a.type",
1402: password: "'password'==a.type",
1403: submit: "'submit'==a.type",
1404: image: "'image'==a.type",
1405: reset: "'reset'==a.type",
1406: button: '"button"==a.type||jQuery.nodeName(a,"button")',
1407: input: "/input|select|textarea|button/i.test(a.nodeName)",
1408:
1409: // :has()
1410: has: "jQuery.find(m[3],a).length",
1411:
1412: // :header
1413: header: "/h\\d/i.test(a.nodeName)",
1414:
1415: // :animated
1416: animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length"
1417: }
1418: },
1419:
1365行目に頻繁に現われるiはマッチした要素の中で何番目かを表すものです。例えば,evenを見ると2で割った余りが0だとtrueになるので,偶数番目の要素だとtrueになるという具合です。
1375行目からは親要素/子要素があるかどうか,テキストノードかどうか,可視要素かどうかを調べるためのものです。
1397行目からは,Form要素のタイプを判別するもので,対象要素のtypeがそれぞれ等しいときにtrueになります。同様にhas()はその要素がみつかればtrue,headerはh1,h2,…のヘッダ要素ならtrue,animatedはアニメーションが動作中の場合にtrueになります。
jQuery.parse(セレクタ式評価用の正規表現)
1420: // The regular expressions that power the parsing engine
1421: parse: [
1422: // Match: [@value='test'], [@foo]
1423: /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
1424:
1425: // Match: :contains('foo')
1426: /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
1427:
1428: // Match: :even, :last-chlid, #id, .class
1429: new RegExp("^([:.#]*)(" + chars + "+)")
1430: ],
1431:
1420行目からは,セレクタ式をパースするための正規表現を定義している部分です。filterメソッドで利用されます。
ここでは3つの正規表現が定義されていて,コメントにあるように1423行目は [@value='test'] または [@foo] のような属性に関するものを扱う場合に利用する正規表現です。また,1426行目は :contains('foo') のように()が付いた擬似セレクタを利用する正規表現です。最後に1429行目が :even, :last-child, #id, .class のような:#.から始まる擬似セレクタとidまたはクラス指定にマッチする正規表現です。
jQuery.multiFilter()
1432: multiFilter: function( expr, elems, not ) {
1433: var old, cur = [];
1434:
1435: while ( expr && expr != old ) {
1436: old = expr;
1437: var f = jQuery.filter( expr, elems, not );
1438: expr = f.t.replace(/^\s*,\s*/, "" );
1439: cur = not ? elems = f.r : jQuery.merge( cur, f.r );
1440: }
1441:
1442: return cur;
1443: },
1444:
1432行目からのjQuery.multiFilter()は内部的に利用するためのメソッドです。次に説明するjQuery.filterメソッドを次々に呼び出していきます。f.tには処理した式は除外されて返ってくるので,'foo, bar'のようなセレクタ式を次々に処理していくことができます。

