この文書は「Selectors API Level 1 (W3C Working Draft 28 June 2012)」の日本語訳である。日本語訳は参考情報であり、公式な文書ではない。また、翻訳に誤りがある可能性にも注意されたい。
原文の最新版 は、この日本語訳が参照した版から更新された可能性がある。他の仕様の訳については Web 標準仕様 日本語訳一覧 を参照されたい。
Copyright © 2006-2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
CSS で広く利用されているセレクタは、木構造をもつ要素群から、目的のものを探すための仕組みである [SELECT][CSS21]。セレクタ API 仕様は、セレクタを指定して DOM から Element
ノードを取り出すメソッドを定義する。この API は、文書の中から特定の要素に対し DOM 操作を行いたい時、とても有用なものだ。このメソッドにより、特定の要素を抽出する処理を、従来の仕組みより簡単に行うことができる。
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This is the 28 June 2012 Last Call Working Draft of "Selectors API". The W3C Membership and other interested parties are invited to review the document and send comments to public-webapps@w3.org (public archive) with [selectors-api] in the subject, through 19 July 2012. (Please note that a different list was used until mid 2008, so some old messages are archived there instead).
Web content and browser developers are encouraged to review this draft. This draft is considered very stable and is expected to progress to Candidate Recommendation after the review period. The Web Applications (WebApps) Working Group has developed a comprehensive Selectors API test suite.
This document was developed by the Web Applications Working Group. The Working Group expects to advance this Working Draft to Recommendation Status.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
このセクションは非規範的である。
この仕様は、与えられたセレクタに対し、そのセレクタにマッチする/しない要素を選択もしくはテストするメソッドを定義する。これらのメソッドにより、従来よりも簡単に Element
ノードを取得できるようになるため、getElementsByTagName()
で得られた結果に対しさらにフィルタをかけるなどといったことをする必要がなくなるだろう。
このセクションは非規範的である。
この例は ECMAScript [ECMA-262] によって書かれている。
HTML 4.01 で、簡単な表を記述する。
<table id="score"> <thead> <tr> <th>Test <th>Result <tfoot> <tr> <th>Average <td>82% <tbody> <tr> <td>A <td>87% <tr> <td>B <td>78% <tr> <td>C <td>81% </table>
たとえば、グラフを描きたいといった理由で、この表から結果 (“Result”) のみを取得したいとしよう。これには2つの方法が考えられる。ひとつは、DOM Level 2 の API のみを利用する方法だ。このやり方では、table
内の tbody
から、各 tr
をイテレートして、その行にある 2 番目のセルを見つけることになる。
var table = document.getElementById("score"); var groups = table.tBodies; var rows = null; var cells = []; for (var i = 0; i < groups.length; i++) { rows = groups[i].rows; for (var j = 0; j < rows.length; j++) { cells.push(rows[j].cells[1]); } }
もう一つは、querySelectorAll()
メソッドを利用する方法だ。このメソッドを使用すると、スクリプトをとても簡潔に記述できる。
var cells = document.querySelectorAll("#score>tbody>tr>td:nth-of-type(2)");
このスクリプトは DOM 上で動作するため、文書がどの構文で書かれているかは関係ないことに注意されたい。つまり、このスクリプトは HTML だけではなく、製形式の XHTML や DOM API を利用し動的に生成され挿入された表に対しても動作するだろう。
仕様書中のすべての図、例、注釈は非規範的なものとなる。また、明示的に非規範的とされたセクションも非規範的なものとなる。それ以外の部分については、規範的なものとなる。
規範的な文章中にあるキーワード must、should、may、recommended は、RFC 2119 で示されるとおりに解釈される [RFC2119].
この仕様では、次の適合性クラスについても検討され、定義されている。
この仕様で利用される用語は、セレクタ仕様のものである [SELECT]。
次の機能は DOM Level 3 Core 仕様で定義される。 [DOM-LEVEL-3-CORE]:
Document
インターフェース
DocumentFragment
インターフェース
Element
インターフェース
NodeList
インターフェース
アルゴリズムとして記された適合性要件や特定のステップについては、結果が同じものである限りどのような方法を用いて実装することも可能だ (may)。
この仕様で利用される IDL は、Web IDL で定義された構文を用いる [WEBIDL]。
Foo
が実際にはインターフェースであるにも関わらず、"Foo
オブジェクト" と表記されることがある。これは、"Foo
インターフェースをインプリメントするオブジェクト" という意味で用いられる。
このセクションは非規範的である。
セレクタの実装状況は、実装により異なる可能性がある。あるセレクタをサポートする実装としない実装が存在する場合、そのセレクタを利用したコードは異なる結果を返すことになるだろう。このため、製作者はこれらの API から投げられる DOM の例外を調べ、Graceful Degradation によるフォールバックを提供することをおすすめする。
このセクションは非規範的である。
この仕様で定義される API の拡張は 奨励されない (strongly discouraged)。実装者やワーキンググループ、そして他の団体は、拡張について public-webapi@w3.org などの公開フォーラムで議論するべきだ。
この仕様を実装するにあたって、ユーザーがセキュリティに関するリスクを負わないようにすることが望まれる。
セキュリティポリシーに違反すると判断される状況に遭遇した場合、実装は処理を中止し、セキュリティ例外を発生させられる (may)。この仕様や関連する仕様の範囲外でエラーが起こった場合、実装は処理を中止し、言語バインディング固有、または実装固有の例外を発生させられる (may)。
プライバシーに関して考えられる懸念のひとつに、履歴の取得が挙げられる。セレクタ [SELECT] の :visited
擬似クラスをクエリーにかけたとき、訪問済みのリンクを取得できることが問題視されている。
しかしながら、これは古くからある問題だ。訪問済みリンクの取得は、CSS と getComputedStyle()
など既存の DOM API により取得できるからだ [DOM-LEVEL-2-STYLE]。
次の例では、vlinks がユーザーが訪れたリンクを取得する。悪意を持った製作者はここから URI を取得し、悪用できる。
var vlinks = document.querySelectorAll(":visited"); for (var i = 0; i < vlinks.length; i++) { doSomethingEvil(vlinks[i].href); }
セレクタ 仕様で定義されている ([SELECT], section 6.6.1) 通り、ユーザーエージェントはすべてのリンクを未訪問のリンクとして扱える (may)。実装には、サポートされるセレクタについて、その他の用途と一貫性を持たせた挙動が推奨される (recommended)。
メソッドの定義で使われる 最初 (first) とは、document order で最初のもの (first in document order) を表す。document order は、該当する DOM ツリーまたはそのサブツリーに対し、深さ優先の先行順走査 (depth-first pre-order traversal) を行ったもの表す。コンテキストノード (context node) は、メソッドが呼び出されるノードを表す。サブツリー (subtrees) は、コンテキストノード の子孫要素のコレクションを表す。マッチする Element
ノード (matching Element
node) は、セレクタの要素マッチング規則 [SELECT] に則り、メソッドに渡されたセレクタ (selectors) にマッチする Element
ノードを表す。
partial interface Document { Element? querySelector(DOMString selectors); NodeList querySelectorAll(DOMString selectors); }; partial interface DocumentFragment { Element? querySelector(DOMString selectors); NodeList querySelectorAll(DOMString selectors); }; partial interface Element { Element? querySelector(DOMString selectors); NodeList querySelectorAll(DOMString selectors); };
querySelector
メソッドと querySelectorAll
メソッド selectors は引数に セレクタ文字列 (selector string) をとる。
Document
, DocumentFragment
, Element
インターフェースの querySelector()
メソッドは、コンテキストノードのサブツリーのなかで、最初にマッチした Element
ノードを返さなければならない (must)。マッチする Element
ノードがない場合、メソッドは null
を返さなければならない (must)。
Document
, DocumentFragment
, Element
インターフェースの querySelectorAll()
メソッドは コンテキストノードのサブツリーのなかで、マッチした Element
ノードすべてを document order で格納した NodeList
を返さなければならない (must)。マッチする Element
ノードがない場合、メソッドは空の NodeList
を返さなければならない (must)。
querySelectorAll()
メソッドから返される NodeList
オブジェクトは 動的 (live) ではなく、静的 (static) でなければならない ([DOM-LEVEL-3-CORE], section 1.1.1) (must)。元文書の構造が変化しても、その変化を NodeList
オブジェクトに反映することは許されない (must not)。つまり、返されるオブジェクトは、リストが生成された時点で文書に存在していたノードに対しクエリをかけ、マッチする Element
ノードを取得することを意味する。
セレクタ文字列 (selector string) とは セレクタのグループ ([SELECT], section 5) を表す。渡されるセレクタは、selectors_group
production ([SELECT], section 10) にマッチすべきだ (should)。ただし、セレクタの前後に 空白文字 ([SELECT], section 4) を含めることが許可されている。また、渡されるセレクタは、解決される必要のある名前空間接頭辞 を利用すべきでない (should not)。
selectors の値に null
や undefined
が渡された場合、実装者は Web IDL [WEBIDL] に従い処理するように望まれている。製作者は、これらの値を渡さないようにすることが望まれている。
擬似要素をセレクタに使うことは可能だが、これは文書中のどの要素にもマッチしないため、何も要素を返さないことになる。このため、製作者はこの使用で定義されるメソッドにおいて、擬似要素を含むセレクタを利用しないことが推奨される。
セレクタのパース (parse a selector) は次のステップで行われる。
このアルゴリズムにおいて、セレクタ文字列 を selectors と定義する。
セレクタ文字列 が dom_selectors_group
の文法にマッチする場合、その文法に従い selectors をパースし、帰ってきた一連のセレクタを result とする。
マッチしない場合、例外 SYNTAX_ERR
を投げ ([DOM-LEVEL-3-CORE], section 1.4) た後にあこのアルゴリズムを終了する。
セレクタの評価 (evaluate a selector) は次のステップで行われる。
評価される要素を element と定義する。
このアルゴリズムに入力されたセレクタを selector group とする。
selector group 中のセレクタがどれかひとつでも element にマッチした場合、true を返す。マッチしない場合は、false を返す。
セレクタが評価される文脈は、与えられた要素が存在する DOM ツリー全体となる。
CSS をサポートするユーザーエージェントにおいて、実装は CSS でサポートするセレクタと同じサポートを API に対しても行うべきだ (should)。
セレクタが 解決される必要のある名前空間接頭辞 を含む場合、実装は 例外 SYNTAX_ERR
を発生させる 必要がある ([DOM-LEVEL-3-CORE], section 1.4) (must)。
この仕様は現在のバージョンにおいて、名前空間接頭辞を解決するメカニズムをサポートしていない。しかし、将来的に追加することを検討している。
解決される必要のある名前空間接頭辞 (namespace prefix needs to be resolved) とは、名前空間コンポーネントが (null 名前空間を表す) 空の状態 (例: |div
) であるものや、どの名前空間をも表すアスタリスク (例: *|div
)、このどちらにも当てはまらないものを表す。アスタリスクや空名前空間接頭辞は解決される必要がないため、セレクタの名前空間構文をサポートする実装は、これら2つをサポートしなければならない [SELECT] (must)。
DOM3 Core では、インターフェースのサポート状況を確かめたり、インターフェースの実装を得たりするため、feature 文字列 (feature strings) を利用するいくつかのメソッドを定義していいる ([DOM-LEVEL-3-CORE], section 1.3.6)。DOM アプリケーションはこのメソッドの引数 feature に "Selectors-API
" を、そして version には "1.0
" を指定することで利用できる。
これらの引数を hasFeature
メソッドに与えたとき、適合する実装は true
を返さなければならない (must)。しかし、true
が返されたとしても、実装が完全に仕様に適合しているわけではなく、また false
が返されたとしても、実装がサポートしている可能性もある。よって、このメソッドの仕様は奨励されない。
このセクションで解説するコードは、次の XHTML 文書を利用している。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Selectors API Example</title> </head> <body> <div id="foo"> <p class="warning">This is a sample warning</p> <p class="error">This is a sample error</p> </div> <div id="bar"> <p>...</p> </div> </body> </html>
メソッドは、複数のセレクタ (カンマ区切り) を引数としてとれる。次の例は、class に "error
" または "warning
" を持つ p
要素すべてを選択する。
var alerts = document.querySelectorAll("p.warning, p.error");
querySelector()
メソッドも複数のセレクタを引数にとれるが、返すのはマッチしたもののうち最初の要素のみとなる。
var x = document.querySelector("#foo, #bar");
x は、ID に foo
または bar
を指定された要素のうち、最初に現れたものを格納する。このセクションの先頭にあるサンプル文書に対しクエリーを実行すると、ID に foo
を持つ div
要素が選択される。なぜなら、この要素は document order 上で最初にマッチするからだ。引数に複数のセレクタを渡しても、その順序は結果に何も影響を及ぼさない。次のように順番を逆にしても、おなじ結果を得られる。
var x = document.querySelector("#bar, #foo");
2つのメソッドは、要素からも呼び出せる。次の例では、イベントハンドラが要素に対して登録されているとする。なので、このメソッドはイベントのターゲットとなる要素から呼び出される。
function handle(evt) { var x = evt.target.querySelector("span"); ... // Do something with x }
メソッドは要素から呼び出されるが、セレクタは文書全体を評価する。次の例において、body
要素は div
要素の子孫でないにも関わらず、メソッドは div
要素の子である p
にマッチする。
var div = document.getElementById("bar"); var p = bar.querySelector("body p");
次のようなナビゲーションメニューを持つ文書があるとする。
<ul class="nav"> <li><a href="/">Home</a></li> <li><a href="/products">Products</a></li> <li><a href="/about">About</a></li> </ul>
次の例は、すべての li
要素を選択し、その結果の NodeList
をイテレートする様子を表す。
var lis = document.querySelectorAll("ul.nav>li"); for (var i = 0; i < lis.length; i++) { process(lis.item(i)); }
ECMAScript では、NodeList
を配列として扱えるため、次のように書き換えられる。
for (var i = 0; i < lis.length; i++) { process(lis[i]); }
メソッドから返される NodeList
オブジェクトは動的ではないため、DOM に行われた変更はリストの内容に影響しない。たとえば、前の例で次の関数 process()
を実行したとする。
function process(elmt) { elmt.parentNode.removeChild(elmt); }
このコードは、DOM から選択された要素ひとつずつを削除するが、各要素は NodeList
に残る。もしリストが動的な NodeList
であれば、DOM から要素を削除したときにリストの要素も変更され、関連する要素のインデックスも調整されるだろう。結果として、ループにおいて意に反する効果が行わる。これは、すべての要素が処理されていないからだ。
複数の名前空間が混在する文書において、それぞれ異なる名前空間に属する要素が、同じローカル名を持つ可能性がある。この API はセレクタの名前空間を解決するメカニズムを備えていないため、特定の名前空間に属する要素を取得するには、何段階かのステップを踏むことになる。次の例は、SVG と XHTML の名前空間が混在する文書から、video
要素を取得するものだ。
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <video id="svgvideo1" xlink:href="myvideo.ogg" width="320" height="240"/> <foreignObject width="100" height="100"> <video id="htmlvideo1" src="myvideo.ogg" xmlns="http://www.w3.org/1999/xhtml">No video1</video> </foreignObject> </svg>
次のスクリプトは、最初に video
要素すべてを取得し、次に名前空間でフィルタをかけ目的の要素のみを抽出する。
var elms = document.querySelectorAll("svg video"); var result = new Array(); var svgns = "http://www.w3.org/2000/svg" for(var i = 0; i < elms.length; i++) { if(elms[i].namespaceURI == svgns) { result.push(elms[i]); } }
The editors would like to thank to the following people who have contributed to this specification (ordered on first name):
Adam van den Hoven, Alan Gresley, Alex Russell, Björn Höhrmann, Boris Zbarsky, Cameron McCormack, Charles McCathieNevile, Chris Wilson, Christophe Jolif, Daniel Glazman, Daniel Schierbeck, Dave Massy, David "liorean" Andersson, David Håsäther, Dean Jackson, Doug Schepers, Erik Dahlström, Francois Remy, Hallvord R. M. Steen, Ian Hickson, Ivan Enderlin, Jean-Yves Bitterlich, Jim Ley, João Eiras, John Resig, Jon Ferraiolo, Jonas Sicking, Jorgen Horstink, Karl Dubost, Kartikaya Gupta, L. David Baron, Maciej Stachowiak, Magnus Kristiansen, Martijn, Masataka Yakura, Mihai Sucan, Mohamed Zergaoui, Nicholas C. Zakas, Nicolas Mendoza, Philip Taylor, Robert Sayre, Robin Berjon, Sander, Sergey Ilinsky, Simon Pieters, Steven Pemberton, Tarquin Wilton-Jones, Travis Leithead, and William J. Edney
Thanks to all those who have helped to improve this specification by sending suggestions and corrections.