[3] [CODE(DOMi)@en[[[Node]]]] [[オブジェクト]]の [DFN[[CODE(DOMm)@en[[[compareDocumentPosition]]]] [[メソッド]]]]は、2つの[[節点]]の[[文書順]]的な意味での関係を返します。

* 仕様書

[REFS[
- [1] [CITE@en-US[Web DOM Core]]
<http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-comparedocumentposition>
- [14] [CITE@en-US[Document Object Model Core]]
-- [2] <http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition>
-- [13] <http://www.w3.org/TR/DOM-Level-3-Core/core.html#DocumentPosition>
- [5] [CITE@en-US[Document Object Model XPath]] 
<http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#DocumentOrder>
]REFS]

[4] 現時点では [[Web DOM Core]] には存在することだけで実質的な規定がまだされていません。
[TIME[2010-12-31T06:40:47.000Z]]

* 引数

[15] この[[メソッド]]は引数を1つだけ取ります。 [SRC[>>2]]

[16] 第1引数 [DFN[[CODE(DOMp)@en[[[other]]]]]] は、比較対象となる [CODE(DOMi)@en[[[Node]]]]
[[オブジェクト]]です。 [SRC[>>2]]

* 返し値

[17] この[[メソッド]]は2[[節点]]間の関係を表す[[ビットマスク]]を返します。[[データ型]]としては
[CODE(IDL)@en[[[unsigned short]]]] です [SRC[>>2]]。

* [CODE(DOM)@en[DocumentPosition]]

[11] 驚くべきことに [[DOM3]] 仕様上は関係がほのめかされているだけで明示されていないのですが、
[CODE(DOMm)@en[[[compareDocumentPosition]]]] は[[定義群]] [DFN[[CODE(DOM)@en[[[DocumentPosition]]]]]]
に属する[[定数]]による[[ビットマスク]]値を返します。

[12] [[界面]] [CODE(DOMi)@en[[[Node]]]] の[[定義群]] [CODE(DOM)@en[[[DocumentPosition]]]] には、
[[データ型]]が [CODE(IDL)@en[[[unsigned short]]]] である以下の[[定数]]があります [SRC[>>13]]。

:[DFN[[CODE(DOMc)@en[[[DOCUMENT_POSITION_DISCONNECTED]]]]]] ([CODE[0x01]]):両[[節点]]は[[連結]]ではありません。 [WEAK[([[連結]]していない[[節点]]の順序は常に[[実装規定]]です。)]]
:[DFN[[CODE(DOMc)@en[[[DOCUMENT_POSITION_PRECEDING]]]]]] ([CODE[0x02]]):与えられた[[節点]]は[[参照節点]]に先行する[[節点]]です。
:[DFN[[CODE(DOMc)@en[[[DOCUMENT_POSITION_FOLLOWING]]]]]] ([CODE[0x04]]):与えられた[[節点]]は[[参照節点]]に後続する[[節点]]です。
:[DFN[[CODE(DOMc)@en[[[DOCUMENT_POSITION_CONTAINS]]]]]] ([CODE[0x08]]):与えられた[[節点]]は、[[参照節点]]を含んでいます。 [WEAK[(含む[[節点]]は常に先行する[[節点]]でもあります。)]]
:[DFN[[CODE(DOMc)@en[[[DOCUMENT_POSITION_CONTAINED_BY]]]]]] ([CODE[0x10]]):与えられた[[節点]]は、[[参照節点]]に含まれています。 [WEAK[(含まれる[[節点]]は常に後続する[[節点]]でもあります。)]]
:[DFN[[CODE(DOMc)@en[[[DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC]]]]]] ([CODE[0x20]]):どちらが先行でどちらが後続かは[[実装規定]]です。

* 処理モデル

[8] この[[メソッド]]がよばれた[[節点]]を[DFN[[RUBYB[参照節点]@en[reference node]]]]とするとき、
[[参照節点]]と第1引数に与えられた[[節点]]についての[[文書]]中での位置を[[文書順]]に基づき調べて[[ビットマスク]]として返します
[SRC[>>2]]。

** ビットマスクの決定

[18] この[[メソッド]]は2[[節点]]間の[[文書]]中の相対位置を表す[[ビットマスク]]を返します。
この値は次のようにして決定されます。 [SRC[>>13]]

= [19] 2[[節点]]が[[同じ節点]]なら、[[フラグ]]は何も設定せずに返します。
= [20] そうでなければ、共通の[[包含子]] (両[[節点]]を[DFN[[RUBYB[[[含む]]]@en[contains]]]][[節点]]) を探します。
=- [21] [[節点]]は、その[[子節点]]を直接含みます。
=- [22] [[節点]]は、[RUBYB[附属している]@en[attached]]他の[[節点]] [WEAK[([[要素]]に対する[[属性]]、[[文書型]]に対する[[実体]]や[[記法]]など)]] を直接含みます。
=- [23] 含まれている[[節点]]に含まれている[[節点]]もまた含まれる[[節点]]ですが、間に挟まる[[節点]]が増えるほど「直接」度は減少していきます。
== [24] 共通の[[包含子]][[節点]]がなければ、
==- [25] 両[[節点]]の[[根]][[包含子]] ([[包含子]]がない[[節点]]つまり最も外側の[[節点]]) 同士の順序によって順序が決定します。
==- [26] 結果は、[[連結]]しておらず、[[実装規定]]です。
==- [27] この結果は、[[根]][[包含子]]が[[メモリー]]上に残っており、他の[[包含子]][[節点]]に[[挿入]]されない限り、[[安定]]です。
== [28] 一方が他方の[[節点]]を含んでいるなら、[[包含子]]が含まれている[[節点]]に先行し、含まれている[[節点]]が[[包含子]]の後続となっています。
== [29] >>24、>>28 のいずれでもない場合には、両方の[[節点]]のどちらの[[包含子]]でもあって、最も「直接」的である[[節点]]が存在するはずです。この場合、そのような[[節点]]が直接含む[[節点]]に、比較対象の[[節点]]または比較対象の[[節点]]を含んでいる[[節点]]が丁度1つずつ、合計2つ存在するので、その順序によって比較対象の[[節点]]の順序が決まります。
=== [30] 両者がともに[[子供節点]]なら、自然な [[DOM]] 上の順序を返します。
=== [31] どちらかが[[子供]]で他方がそうでないなら、[[子供]]である方が[[子供]]で無い方に後続するものとします。例えば[[子要素]]は[[属性]]に後続する ([[属性]]が先行する) とします。
=== [32] どちらも[[子供]]でなく、 [CODE(DOMa)@en[[[nodeType]]]] が異なるなら、大きい順とします。
=== [33] どちらも[[子供]]でなく、 [CODE(DOMa)@en[[[nodeType]]]] も同じなら、順序は[[実装依存]]です。
===- [34] この順序は同じ [CODE(DOMa)@en[[[nodeType]]]] の[[節点]]が直接の[[包含子]]に挿入されたり削除されたりしない限り[[安定]]です。

[35] >>33 が「実装規定」ではなく「実装依存」なのは、typo なのか意図的なのかどうなのでしょうね。

[44] [[Firefox]] でも [[Chrome]] でも、同じ[[要素]]の[[属性節点]]同士だと
[CODE(DOMc)@en[[[DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC]]]] | ([CODE(DOMc)@en[[[DOCUMENT_POSITION_PRECEDING]]]] または 
[CODE(DOMc)@en[[[DOCUMENT_POSITION_FOLLOWING]]]] が返されるようです。違う[[要素]]の[[属性]]ならその所属する[[要素]]の関係で決まるようです。

** 文書順

[6] 「[[文書順]]」は通常の [[DOM]] [[節点]]に対しては [[DOM]] 仕様で定義されていますが、
[[DOM XPath]] 仕様では [CODE(DOMi)@en[[[XPathNamespace]]]] [[節点]]が追加されているため、
それに対応した拡張された「[[文書順]]」が定義されています。
[[DOM XPath]] に対応している場合には拡張された定義に基づき結果を返さなければなりません [SRC[>>5]]。

;; [7] という規定が2004年の [[DOM XPath]] 仕様では [CODE(DOMm)@en[[[compareTreePosition]]]] 
という現存しないメソッド名についてなされていますw

;; [36] でも、 >>18 の処理モデルは「[[文書順]]」の定義を使わずに規定されていますね。

** 異なる実装からの節点の比較

[9] [[DOM3]] は異なる [[DOM]] の実装が混在する環境を扱っています。異なる [[DOM]]
実装からの[[節点]]の比較であっても、両実装の間で「[[実装規定]]」
となっている部分の動作について協調して決定できるのであれば、それに従った結果を返すべきであるようです。

[10] [[節点]]が異なる [[DOM]] 実装のものであり、
「[[実装規定]]」の部分について一貫した結果となるよう協調して動作できない場合、
[[例外]] [CODE(DOM)@en[[[NOT_SUPPORTED_ERR]]]] を[[投げます]]。 [SRC[>>2]]

* 実装

[41] [[Gecko]]、[[WebKit]]、[[Opera]] のいずれも実装しています。 [TIME[2011-01-01T03:47:59.200Z]]

[38] [[WinIE9]] 以降は [[IE9モード]]でのみ対応しています。

;; [37] [CITE@en-us[compareDocumentPosition Method (A, APPLET, attribute, ...)]]
( ([TIME[2010-12-31 21:40:43 +09:00]] 版))
<http://msdn.microsoft.com/en-us/library/ff975125(VS.85).aspx>

* テスト・ケース

[REFS[
- [43] [CITE[Index of /~wakaba/test/web/dom/node/compare]] ([TIME[2012-12-24 22:08:47 +09:00]] 版) <http://suika.fam.cx/~wakaba/test/web/dom/node/compare/>
]REFS]

* 関連

[39] [[要素]]の包含関係を調べる[[メソッド]]には他に [CODE(DOMm)@en[contains][Element.prototype.contains]] があります。
[CODE(DOMm)@en[contains][Element.prototype.contains]] は [CODE(DOMm)@en[[[compareDocumentPosition]]]]
とは違って同じ[[要素]] (自分自身) は「含んでいる」と判断します。

[40] [[要素]]の順序は [CODE(DOMa)@en[[[sourceIndex]]]] [[属性]]の値の比較でも求められます。

[42] [CITE[IRC logs: freenode / #whatwg / 20121015]]
( ([TIME[2012-10-27 16:12:54 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20121015#l-365>

[45] [CITE@en[Make Attr inherit from Node again]]
([[annevk]]著, [TIME[2016-08-19 21:44:07 +09:00]])
<https://github.com/whatwg/dom/commit/625a0747f137454c155a7b577a9e45be1aa35a34>

[46] [CITE@en[Further Attr node fixes for compareDocumentPosition()]]
([[annevk]]著, [TIME[2016-09-01 01:29:21 +09:00]])
<https://github.com/whatwg/dom/commit/0e17e05b7b0273799b853c4782b2eac9a88fdea1>