DOMドキュメントの任意の要素を取り出す方法にはXPathを使うというものがありますが、例によってInternet Explorerでは使えないという問題があります。ではCSSセレクタはどうでしょうか?
これにはW3C Selectors APIというのがあって、FireFoxは実装していますがInternet Explorer 8未満では以下同文という状況のようです。そこは、無いのなら作ってしまえほととぎすという話です。ここではあえて既に実装されているAPIを上書きしています。
CSSセレクタの仕様を完全に実装する必要もなく、JavaScriptから特定の要素を取り出すのに便利な方法が提供できればよいので、
要素名による指定
クラス名による指定(1つのみ)
idによる指定
とそれらの組合せのみを実装しています。(そもそもそんなにCSSセレクタの仕様をしらないのですが)
なお、要素名を省略したときのパフォーマンスが非常に悪化し、特にIEでは顕著となります。つまり、できるだけ上位の指定で要素名を指定して絞り込んだ方がパフォーマンスは有利となります。
document.querySelectorAll = function(selectors, node) {
var result = [];
result.item = function(i) { return this[i]; };
if (!node) node = document;
if (!selectors) { return result; }
//console.log(selectors + " from " + node.nodeName);
if (selectors.match(/^([\w\d]+)?((\.[\w\d\-_]+)|(#[\w\d\-_]+))?\s*/)) {
var ename = RegExp.$1;
var cname = RegExp.$3;
var iname = RegExp.$4;
selectors = RegExp.rightContext;
if (ename && ename != '*') { //tag name
var childs = node.getElementsByTagName(ename);
for (var i = 0; i < childs.length; i++) {
result.push(childs.item(i));
}
} else {
//arguments.calleeで無名関数を再帰的に呼び出す。
(function(curr) {
if (curr.nodeType != 1 && curr.nodeType != 9) return;
result.push(curr);
for (var i = 0; i < curr.childNodes.length; i++) {
arguments.callee(curr.childNodes.item(i));
}
})(node);
}
if (cname) { //class name filter
var pattern = new RegExp(' ' + cname.substring(1) + ' ');
for (var i = result.length - 1; i >= 0; i--) {
var item = result.item(i);
var clazz = (item.className ? item.className : item.styleClass);
if (!(' ' + clazz + ' ').match(pattern))
result.splice(i, 1);
}
}
if (iname) { //id filter
iname = iname.substring(1);
for (var i = result.length - 1; i >= 0; i--) {
var item = result.item(i);
if (item.id != iname)
result.splice(i, 1);
}
}
if (selectors.match(/\S+/)) {
var childs = new Array();
childs.item = function(i) { return this[i]; };
for (var i = 0; i < result.length; i++) {
var q = document.querySelectorAll(selectors, result.item(i));
for (var j = 0; j < q.length; j++) {
childs.push(q.item(j));
}
}
result = childs;
}
return result;
}
}
document.querySelector = function(selectors) {
return document.querySelectorAll(selectors).item(0);
}
【サンプルの実行】
見つかった要素の背景の色が変わります。