2010-02-09

HTML5で規定されている、li要素のvalue属性をサポートしているブラウザがない

最近、私はコードを書くとき、常に規格書を参考にしている。というのも、規格書が一次ソースであるからだ。参考書は二次、三次ソースである。規格書が間違っている可能性は、参考書よりも低いと考えられる。わざわざ間違っている可能性の高い参考書を参照したくはない。

しかし、ことWeb関連の規格に限っては、規格書は全く当てにならない。まして、HTML5は、現実の実装を元に規格を回ているのである。本来とは順番が違うのだ。

HTML5 li elementによると、ol要素の子であるli要素は、value属性を持ち、その値は、要素に対応するリスト番号であるという。

しかし、Chrome, Firefox, Opera, Safariは、このvalue属性をサポートしていなかった。IEはテストしていないので分からない。

この属性は、非常に便利だと思う。querySelectorなどで取得したli要素の番号を取得できるのだ。ところが、主要なブラウザはサポートしていないではないか。

あるいは、deprecatedな属性なのだろうか。しかし、HTML5の規格にある以上は、実装して欲しい。

幸い、今の私のドキュメントでは、CSSでリストの番号をいじるようなことはしていないので、親に対して、何番目のli要素であるかを調べるだけで足る。XHTML限定のコードは、以下の通り。

// calculate nth child element from parent node.
function calculate_nth_li( element )
{
        var parent = element.parentNode ;
        var value = 0 ;
        for ( var i = 0 ; i != parent.childNodes.length ; ++i )
        {
                var node = parent.childNodes.item( i ) ;
                if ( node.nodeType == node.ELEMENT_NODE && node.nodeName == "li" )
                {
                        ++value ;
                        if ( element.isSameNode( node ) )
                                return value ;
                }
                
        }
        // shall not reach here.
}

親に対して、何番目のノードの子であるかを取得する方法が、DOMで規定されていれば便利だろう、と思ったが、考えてみれば、ノードは、要素だけとは限らない。テキストとかコメントなどもある。現実的には、あまり役に立ちそうもない。

コメントで、Element Traversal SpecificationというすばらしいDOM規格があることを教えてもらった。さっそく、これを使って上記の関数を書き直した。

function nth_child_element( element )
{
        var n = 1 ;
        var iter = element.parentNode.firstElementChild ;
        while ( !iter.isSameNode( element ) )
        {
                ++n ;
                iter = iter.nextElementSibling ;
        }

        return n ;
}

コードを簡潔にするため、li要素かどうかの判定はなくした。なぜならば、規格準拠のXHTML5では、ol要素の直接の子は、かならずli要素でなければならないからだ。このコードは、私の書いたドキュメントにしか適用しない。そして私は、常に規格準拠のXHTMLを書くよう心がけているので、全く問題はない。

冷静に考えれば、Element Traversalと同等機能は、DOM level 2 coreを使って、自前で実装することもできる。しかし、このような単純なものは、標準にあった方がいい。

2 comments:

os0x said...

Element Traversal
http://www.w3.org/TR/2008/WD-ElementTraversal-20080303/
を使うと少しきれいに書けると思います(仕様にはchildElements相当のAPIがないんですが、代わりに各ブラウザはchildrenを実装してます)。
また、XPathで自分より前の兄弟要素の数を調べれば、一発で調べることは可能ですね。XPath自体が面倒なので微妙なところですが。

江添亮 said...

おお、これはすばらしい。
W3C DOM Compatibility - Traversal
を見ても、最新の主要なブラウザは、すべて実装していますね。
親に対して何番目の子かという、そのものズバリの属性はないものの、これは使える。

XPathをXHTMLに対して適用しようとすると、名前空間との兼ね合いで、悲惨なことになります。
もう諦めました。
結局、世間もXPathなんて忘れて、querySelector相当のライブラリが乱立しましたからね。
querySelectorが規格化されたのも、むべなるかな。