Positionオブジェクト(3)
realOffsetメソッド
【抜粋】 realOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return [valueL, valueT]; },
引数の要素と、その親要素すべてのscrollLeftプロパティとscrollTopプロパティの累積値を返却するメソッド。返却値は[(scrollLeftプロパティ累積値), (scrollTopプロパティ累積値)]形式の配列です。累積値にはウィンドウのスクロールも含まれます。
なぜか引数の要素はID指定が不可です・・・。いままでOKだったのに。。。
【例】 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN"> <html> <head> <title></title> <style> <!-- #scroll1{ border:solid blue 2px; overflow:scroll; position:relative; width:400px; height:400px; } #scroll2{ border:solid blue 2px; overflow:scroll; position:relative; width:200px; height:200px; margin:90px; } #base1{ width:600px; height:600px; } #base2{ width:300px; height:300px; } #mark{ background-color:red; position:relative; top:120px; left:120px; width:20px; height:20px; } --> </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> <!-- function test(){ var str = "Position.realOffset($('mark')) = " + Object.inspect(Position.realOffset($('mark'))); Element.update('view', str); } //--> </script> </head> <body> <div id="scroll1"> <div id="base1"> <div id="scroll2"> <div id="base2"> <div id="mark"> MARK </div> </div> </div> </div> </div> <button id="test" onclick="test();">TEST</button> <div id="view"></div> </body> </html>
TESTボタンを押すと要素MARKまでのスクロール量が表示されます。要素やウィンドウのスクロールバーを動かしてからTESTボタンを押すと表示される値が変更されます。
なぜリアルなのかは不明。。。
cumulativeOffsetメソッド
【抜粋】 cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return [valueL, valueT]; },
引数の要素と、その親要素すべてのoffsetLeftプロパティとoffsetTopプロパティの累積値を返却するメソッド。返却値は[(offsetLeftプロパティ累積値), (offsetTopプロパティ累積値)]形式の配列です。
要素のoffsetParentプロパティは、offsetLeft、offsetTopの基準となる要素を格納しています。通常はbody要素ですが、場合によって変化します。(「何を基準要素(offsetParent)とするか」はかなりややこしい話になります。「offsetTop/offsetLeft/offsetParentの闇 - Backstage of theater.js」を参照してください。)
ブラウザがKonqueror、Safari、KHTMLの場合、最後に別定義で上書きされます。
枠線幅問題
枠線幅があるとOpera以外で正しく値が取れません(以前の例に枠線があったので修正しました)。
「Positionオブジェクト(1) - Backstage of theater.js」の「枠線幅問題」を参照してください。
【例】 <html> <head> <title></title> <style> <!-- #parent{ left:200px; background-color:yellow; position:relative; width:200px; height:200px; } #mark{ background-color:red; position:relative; top:100px; left:100px; width:20px; height:20px; } --> </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> <!-- function test(){ var str = "Position.cumulativeOffset($('mark')) = " + Object.inspect(Position.cumulativeOffset($('mark'))) + "<br/>" + "$('mark').offsetLeft/Top = " + $('mark').offsetLeft + ", " + $('mark').offsetTop; Element.update('view', str); } //--> </script> </head> <body> <div id="parent"> <div id="mark"> MARK </div> </div> <button id="test" onclick="test();">TEST</button> <div id="view"></div> </body> </html>
TESTボタンを押すと、要素markを引数としたrealOffsetメソッド返却値と、要素markのoffsetLeft、offsetTopプロパティを表示します。 position:relative;の親要素内の子要素の場合、offsetLeft、offsetTopはその親要素を基準にします。
positionedOffsetメソッド
【抜粋】 positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { p = Element.getStyle(element, 'position'); if (p == 'relative' || p == 'absolute') break; } } while (element); return [valueL, valueT]; },
cumulativeOffsetメソッドとの違いは、累積中に、offsetParentプロパティの要素がposition:relativeもしくはabsoluteの場合、そこで累積を中止する点です。position:relative/absolute;の要素の値は加算されません。
【例】 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN"> <html> <head> <title></title> <style> <!-- #parent{ position:relative; left:200px; background-color:yellow; position:relative; width:400px; height:400px; } table{ background-color:blue; margin:50px; } td{ background-color:white; padding:5px; } #base{ width:300px; height:300px; } #mark{ background-color:red; width:20px; height:20px; } --> </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> <!-- function test(){ var str = "Position.positionedOffset($('mark')) = " + Object.inspect(Position.positionedOffset($('mark'))) + "<br/>" + "$('mark').offsetLeft/Top = " + $('mark').offsetLeft + ", " + $('mark').offsetTop; Element.update('view', str); } //--> </script> </head> <body> <div id="parent"> <table><tr><td> <div id="mark"> MARK </div> </td></tr></table> </div> <button id="test" onclick="test();">TEST</button> <div id="view"></div> </body> </html>
上記例の実行結果は以下です。
(IE6) Position.positionedOffset($('mark')) = [57, 57] $('mark').offsetLeft/Top = 5, 5
td要素は要素markのoffsetParentになります。
枠線幅問題
ここでも枠線幅があるとOpera以外で正しく値が取れません(以前の例に枠線があったので修正しました)。「Positionオブジェクト(1) - Backstage of theater.js」の「枠線幅問題」を参照してください。
offsetTop/offsetLeft/offsetParentの闇・・・
いままで、なんとなくoffsetTopやoffsetLeftを使っていましたが、よくよく調べてみると奥が深い、というより滅茶苦茶です。嫌になるくらい、ブラウザ間で微妙に違います。→調査結果を「offsetTop/offsetLeft/offsetParentの闇 - Backstage of theater.js」にまとめました。