Positionオブジェクト(2)

prepareメソッド

【抜粋】
  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

deltaXプロパティにページの横スクロール位置(px)、deltaYプロパティにページの縦スクロール位置(px)を設定するメソッド。ブラウザによって取得方法が違うため、こんなになってます。

対応を調べてみました。

window
.page[X/Y]Offset
document
.documentElement
.scroll[Left/Top]
document
.body
.scroll[Left/Top]
IE6
(Quirks mode)
undefined 0 (value)
IE6
(Standards mode)
undefined (value) 0
Netscape7.1 (value) 0 (value)
Firefox1.5.0.4
(Quirks mode)
(value) 0 (value)
Firefox1.5.0.4
(Standards mode)
(value) (value) 0
Opera9.0 (value) (value) (value)

見事にバラバラ・・・orz

IEではStandards modeのとき、画面のスクロール位置は、body要素ではなくてhtml要素に設定されます。Standards modeではページのコンテンツはbody要素の上でなくhtml要素の上に載っているとみなされるらしいです。ので、document.documentElementのプロパティを使用しています

・・・困ったちゃんのIEに、他のみんなが一生懸命合わせようとしているような^^;

参考
Quirks mode、Standards mode:
  >文書型宣言と解釈モード - Backstage of theater.js
document.documentElement:
  >http://tomizawa-web.hp.infoseek.co.jp/property/documentElement.htm

コード中のコメントの意味は以下。
「ページスクロールしたら、withinIncludingScrolloffsetメソッドを呼び出す前に必ず呼び出すこと。」
デフォルト位置でも呼び出す必要があります。その後、ページスクロールした後(またはユーザによりスクロールされていることが予想される場合)、withinIncludingScrolloffsetメソッドを呼び出す場合は、このprepareメソッドを呼び出す必要があります。

前述したように、withinIncludingScrolloffsetメソッドは、includeScrollOffsetsプロパティがtrueのときに、withinメソッドから処理を任されるメソッドです。なので、withinメソッド呼び出し前に、prepareメソッドを場合によっては呼び出す必要がある、ということでもあります。その条件はincludeScrollOffsetsプロパティがtrueのとき、つまり「スクロール可能要素内にドラッガブル要素が含まれる場合」です。実は、前述のincludeScrollOffsetsプロパティの例で、無断で使用しています。すみません^^;

無論、単にスクロール位置を取得するために使用することもできます。

なんでいちいちプロパティに設定して使っているのかはちょっと謎です。パフォーマンスにそれほど影響があるようには思えないのですが。考えられるのは、その時点のスクロール位置を基準として使用したい場合に、保持して使用するため、というのがあります。が、それならプログラムで何とでもなると思うのですが・・・。何か分かったら追記します。

【例】
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><!--Quirks mode-->
<!--<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">--><!--Standards mode-->
<!--modeを切り替えるときはコメントアウトおよび位置を入れ替える-->
<html>
<head>
<title></title>
<style>
<!--
#test{
  height:1000px;
  width:1000px;
  background-color:lemonchiffon;
}
-->
</style>
<script language="javascript" src="prototype.js" charset="utf-8"></script>
<script>
<!--
function test(){
  Position.prepare();
  alert(Position.deltaX + "," + Position.deltaY);
  
  //参考 縦スクロール位置が設定されるプロパティの調査
  var str =  "<table border><caption>縦スクロール位置のプロパティ調査</caption>"
          +  "<tr><td>window.pageYOffset</td>"
          +  "<td>" + window.pageYOffset + "</td></tr>"
          +  "<tr><td>document.documentElement.scrollTop</td>"
          +  "<td>" + document.documentElement.scrollTop + "</td></tr>"
          +  "<tr><td>document.body.scrollTop</td>"
          +  "<td>" + document.body.scrollTop + "</td></tr></table>";
  Element.update('test', str);
}
//-->
</script>
</head>
<body>
<div id="test" onclick="test();" title="クリックするとスクロール位置を表示します">
</div>
</body>
</html>

div要素testの上でクリックすると、スクロール位置をalertで表示します。おまけで、縦スクロール位置のプロパティを表示してみました。興味があれば各ブラウザでお試しください。modeは!DOCTYPE宣言を変更してください*1

*1:必ずファイルの先頭に記述してください。コメントでも前にあると正しく動作しません