Home > JavaScript > Safari バグ: TD エレメントの間違った offsetTop 値

Safari バグ: TD エレメントの間違った offsetTop 値

# 追記: このバグは最新の開発版では修正されています。WebKit Bugzilla を参照のこと→ WebKit Bugzilla 19094. Nightly でも既に修正されているみたいですね。もしこれに関してハックをしたなら(つまり僕のことですが)、以下のようなもう一つ、ハックが必要です。

var webkit = indow.navigator.userAgent.match(/WebKit\/([0-9]{3})/);
if (webkit && parseInt(webkit[1]) < 528) {
...
}

JavaScript ライブラリの多くは、HTML エレメントの(ページ上での)ピクセル位置(絶対座標)を返すメソッドを備えています。jQuery の jQuery.offset() しかり、MochiKit の MochiKit.Style.getElementPosition() しかり、MooTools の Element.getPosition() 等々… ほとんどの場合これらはうまく動くのですが、今日動かないケースを確認し、おそらく Safari のバグだと思うのでここに報告しておきます。

以下の条件が揃ったとき、ピクセル絶対座標を取得するメソッドは間違った値を返します。

  1. ブラウザは Safari
  2. 取得しようとしているエレメントは TD (あるいは display:table-cell)
  3. CSS で vertical-align を top 以外の値 (middle or bottom) が設定されている

次にこのケースの例を作りました。Safaribug: wrong offsetTop on TD. テーブルセルをクリックすると、アラートで、そのテーブルセルのピクセル座標を返します。Safari とその他のブラウザで開いてみてください。違いがあります。

ではコードで解説します。以下は Google doctype project で見つけた PageOffset: How to calculate the position of an element on the page (goog.style.getPageOffset) を下にしています。オリジナルの PageOffset のコードは非常に細かく説明してあるので、一度読んで見ることをお勧めします。長くないし。

function getPageOffset(el) {
    var pos = {
        x: 0,
        y: 0
    };
    var viewportElement = document;
    if (el == viewportElement) {
        return pos;
    }

    var parent = null;
    var box;

    pos.x = el.offsetLeft;
    pos.y = el.offsetTop;

    parent = el.offsetParent;
    if (parent != el) {
        while (parent) {
            pos.x += parent.offsetLeft;
            pos.y += parent.offsetTop;
            parent = parent.offsetParent;
        }
    }

    if (el.style.position == 'absolute') {
        pos.y -= doc.body.offsetTop;
    }

    parent = el.offsetParent;
    while (parent && parent != document.body) {
        pos.x -= parent.scrollLeft;
        parent = parent.offsetParent;
    }

    return pos;
};

Safari では、指定したエレメントから、その相対目標(これを指定しなければ、document.body を相対目標とします。つまりページの絶対座標ですね。)まで、エレメントを上り詰めて、その間の offset を累積加算していきます。問題は、一番最初の el.offsetTop (15行目) で起こります。これは table cell で、padding/margin/border が設定されていませんから、0 であるべきなのですが、Safari は、子孫要素への offset を返しているようなんですね。

どうにもいい方法が見つからなかったので、実際のアプリケーションではダーティハックを入れましたが、WebKit チームの早急な fix を望みます!!

Comments:0

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://blog.nydd.org/2009/03/safari-%e3%83%90%e3%82%b0-td-%e3%82%a8%e3%83%ac%e3%83%a1%e3%83%b3%e3%83%88%e3%81%ae%e9%96%93%e9%81%95%e3%81%a3%e3%81%9f-offsettop-%e5%80%a4/trackback/
Listed below are links to weblogs that reference
Safari バグ: TD エレメントの間違った offsetTop 値 from Vantage Point of Queens

Home > JavaScript > Safari バグ: TD エレメントの間違った offsetTop 値

Search
Feeds
Meta
Links
Ads!

Return to page top