待望の document.elementFromPoint が実装

待望の document.elementFromPoint が Firefox 3.0a8pre にて実装された。仕様は nsIDOMNSDocument.idl に詳しく書いてあるが、おおよそ以下の通りである。

  • HTML, XUL どちらの document に対しても使用可能
  • document の左上を (0, 0) とし、位置 (x, y) にある実際に見えている要素を取得する
  • 同一の document 内に存在する要素のみ取得可能。例えばインナーフレーム内の document 内に存在する要素は取得できず、代わりに iframe 要素を返す。
  • 位置 (x, y) が document の可視領域の外側にある場合、null を返す。
  • XUL document で使用する場合、例えば textbox 要素のスクロールバーのように XBL で生成された無名要素は取得できない。この場合、 textbox 要素を返す。
  • XUL document で使用する場合、 onload イベント発生以降でなければならない。

さっそく使い心地を試すべく、 HTML の document についてのサンプルをブックマークレットとして作った。使い方は、 Firefox 3 で適当なページを開き、下記のコードを丸ごとコピーしてロケーションバーへ貼り付けて移動するだけ。マウスポインタ上に位置する要素を elementFromPoint で取得してツールチップ風に表示する。

サンプル1

javascript:(function(){
    var tooltip = document.createElement("DIV");
    tooltip.style.cssText = "position: absolute; z-index: 1000; background-color: lightgreen;";
    document.body.appendChild(tooltip);
    var scanElement = function(event) {
        var elt = document.elementFromPoint(event.clientX, event.clientY);
        tooltip.innerHTML = "(" + event.clientX + ", " + event.clientY + ") " + elt.tagName;
        tooltip.style.left = (event.clientX + window.scrollX) + "px";
        tooltip.style.top  = (event.clientY + window.scrollY + 21) + "px";
    };
    document.addEventListener("mousemove", scanElement, false);
})();

しかし、上記の例はわざわざ elementFromPoint を使わなくても event.target で代用可能なので面白みがない。そこで、より機械的に指定した座標の要素を取得する例を作った。ページ左上から斜めに移動しながら要素名を取得して表示する。

サンプル2

javascript:(function(){
    var tooltip = document.createElement("DIV");
    tooltip.style.cssText = "position: absolute; z-index: 1000; background-color: lightgreen;";
    document.body.appendChild(tooltip);
    var scanElement = function(posX, posY) {
        var elt = document.elementFromPoint(posX, posY);
        tooltip.innerHTML = "(" + posX + ", " + posY + ") " + elt.tagName;
        tooltip.style.left = (posX + 2) + "px";
        tooltip.style.top  = (posY + 2) + "px";
        setTimeout(function(){ scanElement(++posX, ++posY); }, 20);
    };
    window.scrollTo(0, 0);
    scanElement(0, 0);
})();

TOP

TOP