javascriptの優れたライブラリが近年続々と公開されています。
幸いな事にprototype.js、jQuery、そして最近ではさらにamachangさんによるライブラリによってjavascriptによるDOM要素抽出が気軽に見通しよく記述することができる環境が整っているようです。
車輪の再実装ですがタグ名とクラス名を指定してDOM要素抽出を行なうという用途のための小さなコードを書きました。既存ライブラリを使わない小さなサイズのスクリプトでちょっとしたDOM操作のために。
使い方はgetBoxes(klass, tag) でクラス属性値klass、タグ名tagのDOM要素を配列にして抽出します。tagを省略すると、指定されたクラス属性値を持つ全てのタグを抽出します。
たとえば、getBoxes('test', 'div') では、testをクラス属性値に持つタグ名divの要素を配列で返します。
■追記:2007/11/12
getBoxes(klass, tag, context) のように第3引数にDOM要素を指定すると、その要素と子孫要素が探索対象範囲となる機能を追加しました。第3引数を指定しなければページ内の全要素が探索対象となります。
XPathを使用する場合、XPath式とnamespace resolver(ここでは、nullです)から生成されるオブジェクトを保存し再利用するようにしました。
var getBoxes
= (/Firefox\/(\d+)/.test(navigator.userAgent) && RegExp.$1 > 2) ?
(function(){
var toChangeCase = (document.documentElement.nodeName == 'HTML')
? 'toUpperCase' : 'toLowerCase';
return function(klass, tag, context){
var boxes = (context || document).getElementsByClassName(klass);
return (tag && (tag = tag[toChangeCase]()))
? Array.filter(boxes, function(e){return e.nodeName == tag;})
: boxes;
};
})()
: (document.implementation && document.implementation.hasFeature && document.implementation.hasFeature('XPath', '3.0')) ?
(function(){
var toChangeCase = (document.evaluate('//*[local-name()="HTML"]', document, null, XPathResult.BOOLEAN_TYPE, null).booleanValue)
? 'toUpperCase' : 'toLowerCase',
cache = {};
return function(klass, tag, context){
var boxes = [],
key = (tag || '*') + ':' + klass,
exp = cache[key] ||
(cache[key] = document.createExpression('//*'
+ (tag ? ('[local-name()="' + tag[toChangeCase]() + '"]') : '')
+ '[contains(concat(" ",@class," ")," ' + klass + ' ")]', null)),
nodes = exp.evaluate(context || document, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null),
node,
i = 0;
if(nodes)
while(node = nodes.iterateNext())
boxes[i++] = node;
return boxes;
};
})()
: function(klass, tag, context){
var boxes = [],
regex = new RegExp('(?:^|\\s)' + klass + '(?:\\s|$)'),
i = 0;
/*@cc_on
if(@_jscript_version > 5.5 || @_mac || tag || !context){
@*/
var nodes = /*@cc_on (@_jscript_version < 5.6 && !@_mac && !tag && !context) ? document.all : @*/
(context || document).getElementsByTagName(tag && tag.toLowerCase() || '*'),
node,
j = 0;
if(nodes)
while(node = nodes[i++])
if(regex.test(node.className))
boxes[j++] = node;
/*@cc_on
}else{
(function walk(e){
if(e.nodeType == 1 && regex.test(e.className)) boxes[i++] = e;
e = e.firstChild;
while(e){
walk(e);
e = e.nextSibling;
};
})(context);
};@*/
return boxes;
};
資料
- getElementsByClassName on Gecko: Days on the Moon
- DOM:document.getElementsByClassName - MDC
- HTML 5 Working Draft
Firefox3で導入されるgetElementsByClassNameの仕様・特徴について。 -
John Resig - getElementsByClassName Speed Comparison
jQuery作者John Resigさんによるクラス属性値を指定した各種要素抽出方法の性能比較。 Firefox3で実装されるdocument.getElementsByClassNameが現状で最も高速。次いでXPath、DOMの順とのこと。 - FirefoxのXPathEvaluator
Firefoxに実装されているXPathEvaluatorの速度計測。 - google-code-prettify - Google Code
このエントリーで使用しているjavascriptによるシンタックスハイライト・ライブラリです。 - 日本の伝統色 和色大辞典 - Japanese Traditional Color Names
こんなに多くの呼び名があることに驚きです。シンタックスカラーの参考にしました。 - Latest topics > CSS3セレクタとXPathでの表現の対応表 - outsider reflex
丁寧に詳しい説明です。 - XPath, $X function, NSResolver < 16 < March < 2006 < nulog, NULL::something : out of the headphone
XHTMLでの名前空間、XPathのNamespace Resolverについて。

0 件のコメント:
コメントを投稿