ElementTraversalインターフェイスを実装する

多くのブラウザ(Opera 9.6、Google Chrome 2、Safari 4、Firefox 3.5)が非常に便利なElementTraversalインターフェイスをサポートしました。これにより、テキストノードを無視してDOMツリー内を移動できます。 これらのブラウザでは、各要素について、次の一連の新しいゲッターが利用可能になりました。 これらのゲッターの実装の詳細に入ることなく、仕様の言葉に依存することなく:

ElementTraversalインターフェースは、読み取り専用属性のセットです ...
それらをさらに属性と呼びます。



明確にします:要素は、nodeTypeプロパティが1のDOMツリーのノードです。 タグは要素に対応します。



nodeTypeループでノードをチェックして追加のラッパー関数を使用する必要がないため、これらの属性を使用すると、DOMツリーを移動する際のJavaScriptアプリケーションのパフォーマンスが向上します。 また、childElementCount属性を使用すると、実際には役に立たないhasChildNodesメソッドとは対照的に、現在のノードに子があるかどうかを確認できます。 もちろん、次のようにして子要素の存在を確認できます。

node.getElementsByTagName( "*" ).length



しかし、このメソッドは無駄が多すぎるため、組み込み属性childElementCountは理論的にははるかに高速に動作するはずです。



もちろん、これはすべて素晴らしく興味深いものですが、ElementTraversalインターフェースをサポートしていない古いブラウザーをどうするのでしょうか? 明らかに、属性ごとに追加の関数を作成する必要があります。 それらの実装は記事「 DOM要素のクイック検索 」で見ることができますが、多くの人がそのような関数を自分で書くことは難しくないと思いますが、複雑なことは何もありません。



そして今、最も興味深いのは、Internet Explorer 8でこれらの同じゲッターとセッターを作成する機会がありました。 唯一の奇妙なことは、IE8がこの強力で有用なメカニズムに言及しなかったのは、イノベーションのレビューがない理由です。 JScriptでは、組み込みオブジェクトのdefinePropertyメソッドを使用してゲッターまたはセッターを作成できるようになりました。 __defineGetter__メソッドと__defineSetter__メソッドを使用した同様の機会が、もともとGeckoベースのブラウザーであったことを思い出します。Safari3で既に判明しており、Opera 9.6でこのメカニズムが導入されました。



そのため、ゲッターを作成する機能があれば、Internet Explorer 8、Mozilla Firefox 2+およびSafari 3+でElementTraversalインターフェイスのサポートを実装できますが、Opera 9.6はすでにサポートしています。



コードを書くことは残っています:

// <br> var element = document .createElement( "div" );<br><br> // , ElementTraversal <br> if ( typeof element.firstElementChild == "undefined" ) {<br><br> // <br> var ElementTravrsal = {<br><br> // <br> firstElementChild: function () {<br> // <br> var node = this .firstChild;<br> // <br> // null <br> while (node && node.nodeType != 1) node = node.nextSibling;<br> // null <br> return node;<br> },<br><br> // <br> lastElementChild: function () {<br> // <br> var node = this .lastChild;<br> // <br> // null <br> while (node && node.nodeType != 1) node = node.previousSibling;<br> // null <br> return node;<br> },<br><br> // <br> nextElementSibling: function () {<br> // <br> // <br> var node = this ;<br> // <br> // null <br> do node = node.nextSibling<br> while (node && node.nodeType != 1);<br> // null <br> return node;<br> },<br><br> // <br> previousElementSibling: function () {<br> // <br> // <br> var node = this ;<br> // <br> // null <br> do node = node.previousSibling;<br> while (node && node.nodeType != 1);<br> // null <br> return node;<br> },<br><br> // <br> // , children <br> childElementCount: typeof element.children == "undefined" ? function () {<br> // children, <br> // <br> var list = this .childNodes,<br> // <br> i = list.length,<br> // <br> j = 0;<br> // , <br> while (i--)<br> // , <br> if (list[i].nodeType == 1)<br> // <br> j++;<br> // 0 <br> return j;<br> } : function () {<br> // children, <br> // <br> // <br> return this .children.length;<br> }<br> };<br><br> // IE8 <br> if (Object.defineProperty)<br> for ( var property in ElementTravrsal)<br> if (ElementTravrsal.hasOwnProperty(property))<br> Object.defineProperty(Element.prototype, property, {<br> get: ElementTravrsal[property]<br> });<br><br> // Firefox 2+ Safari 3+ <br> if (Object.__defineGetter__)<br> for ( var property in ElementTravrsal)<br> if (ElementTravrsal.hasOwnProperty(property))<br> HTMLElement.prototype.__defineGetter__(property, ElementTravrsal[property]);<br><br>}



このコードをプロジェクトに含めると、ほとんどのブラウザーでElementTraversalを使用できるようになりました。 一部のサービスまたは管理インターフェイスの開発には、このリストで十分です。 すべてのブラウザのサポートが必要な場合、上記のリンクを使用した上記の記事のように、追加の機能なしでは実行できません。 または、サポートされているブラウザのリストを展開できますか? 他のブラウザでこれを行う方法についてアイデアがあれば、コメントを書いてください。たとえこれらが非合理的なソリューションであっても、実装の可能性は非常に興味深いものです。



新しいインターフェイスの属性は、古いfirstChild、lastChild、nextSiblingなどと同じ方法で使用されます。たとえば、次のようなXHTMLコードを使用します。

< div id ="test" > <br> TextNode<br> < div > TextNode </ div > <br> TextNode<br> < p > TextNode </ p > <br> TextNode<br> </ div > <br>TextNode<br> < p > TextNode </ p >



JavaScriptでDOMツリーの周りをいくつか移動します。

// <br> // "test" <br> var node = document .getElementById( "test" );<br><br> // tagName <br>alert(node.nextElementSibling.tagName); // → "P" <br><br> // <br>node = node.lastElementChild;<br><br> // , ? <br>alert(node.childElementCount); // → "0" <br><br> // ? <br>alert(node.hasChildNodes()); // → "true"



面白かった場合は、次の記事でJScriptとJavaScriptでゲッターとセッターを使用する方法について詳しく説明します。



記事のコードでアーカイブ: ElementTraversal.zip



更新:テーマブログに移動しました。カルマに感謝します:-)



All Articles