2006.11.02

スクロール付きDIVのサイズを動的に変更する

※注意:IE限定です。
スクロール付きDIVのサイズをウィンドウサイズに合わせて動的に変更する必要があった。ウィンドウの幅に合わせるには、ウィンドウの幅からDIVの左絶対座標を引いた値をDIVの幅へ設定すればよい。いろいろ調べた結果、入子になったコンテナの絶対座標を取得する属性は存在せず、親コンテナからの相対座標しか取得できないようだ。そのため、絶対座標を取得したいコンテナから親をたどってbodyまでの相対座標を合算する処理を記述する必要がある。それらに必要な属性は以下のとおり。

bodyの表示幅: document.body.clientWidth
コンテナのborder幅:obj.clientLeft(Top)
親コンテナからの距離:obj.offsetLeft(Top)

てな分けで、コンテナを渡すと絶対座標を取得してくれるObjectを作ってみた。

function AbsPos(obj) {
    this.left = 0;
    this.top  = 0;
    this.rewind = function(obj,start) {
        if (obj == document.body) return ;
        this.left += obj.offsetLeft;
        this.top  += obj.offsetTop;
        if (!start && (obj.tagName == 'TD' || obj.tagName == 'TH')) {
            this.left += obj.clientLeft;
            this.top  += obj.clientTop;
        }
        this.rewind(obj.offsetParent, false);
    }
    this.rewind(obj, true);
}

使い方は、

var pos = new AbsPos(obj);
alert(pos.left);
alert(pos.top);

などとする。取得される値は目的のコンテナのborderの外側が取得できる。TH、TD内のコンテナについては正しくoffsetLeft(Top)が取得できないようなので、少々こじつけている。
以下のようはHTMLで検証できる。

<html>
<head>
    <script language="javascript" type="text/javascript">
    function AbsPos(obj) {

        this.left = 0;
        this.top  = 0;
        this.rewind = function(obj,start) {
            if (obj == document.body) return ;
            this.left += obj.offsetLeft;
            this.top  += obj.offsetTop;
            if (!start && (obj.tagName == 'TD' || obj.tagName == 'TH')) {
                this.left += obj.clientLeft;
                this.top  += obj.clientTop;
            }
            this.rewind(obj.offsetParent, false);
        }
        this.rewind(obj, true);
    }
    function getAbsPos(obj) {
        var pos = new AbsPos(obj);
        var lineTop = document.createElement("IMG");
        lineTop.style.position          = 'absolute';
        lineTop.style.backgroundColor   = 'red';
        lineTop.style.border            = '0px solid blue';
        lineTop.style.width             = document.body.clientWidth;
        lineTop.style.height            = '1px';
        lineTop.style.left              = '0px';
        lineTop.style.top               = pos.top;
        document.body.appendChild(lineTop);

        var lineLeft = document.createElement("IMG");
        lineLeft.style.position          = 'absolute';
        lineLeft.style.backgroundColor   = 'red';
        lineLeft.style.border            = '0px solid blue';
        lineLeft.style.width             = '1px';
        lineLeft.style.height            = document.body.clientHeight;
        lineLeft.style.left              = pos.left;
        lineLeft.style.top               = '0px';
        document.body.appendChild(lineLeft);
    }
    </script>
    <style>
        *
    {
     border-width: 0px;
     border-style:solid;
     margin:0px;
     padding:0px;
    }
    </style>

</head>
<body style="border-color: red; border-width: 0px;">
    <div style="border-color: blue; border-width: 51px;">
        <table style="border-color: yellow; border-width: 15px;" onclick="getAbsPos(this);">
            <tr>
                <th style="border-color: green; border-width: 5px; padding:10px;" onclick="getAbsPos(this);">
                    <div id="hoge" style="border-color: gray; border-width: 5px; margin:20px;" onclick="getAbsPos(this);">
                        hoge
                        <div id="Div1" style="border-color: Cyan; border-width: 5px;" onclick="getAbsPos(this);">
                            ukeke</div>
                    </div>
                </th>
                <td>
                    <span onclick="getAbsPos(this);" style="border-color: gray;">hoge</span>
                </td>
            </tr>
            <tr>
                <td>
                    <span onclick="getAbsPos(this);" style="border-color: gray;">hoge</span>
                </td>
                <td>
                    <span onclick="getAbsPos(this);" style="border-color: gray;">hoge</span>
                </td>
            </tr>
        </table>
        <div style="border-color: green; border-width: 8px;">
            <div style="border-color: gray; border-width: 3px;" onclick="getAbsPos(this);">
                hoge
            </div>
        </div>
    </div>
</body>
</html>

でこれをつかってDIVの幅を動的に変更するサンプル

<html>
<head>
    <script language="javascript" type="text/javascript">
    function AbsPos(obj) {
        this.left = 0;
        this.top  = 0;
        this.rewind = function(obj,start) {
            if (obj == document.body) return ;
            this.left += obj.offsetLeft;
            this.top  += obj.offsetTop;
            if (!start && (obj.tagName == 'TD' || obj.tagName == 'TH')) {
                this.left += obj.clientLeft;
                this.top  += obj.clientTop;
            }
            this.rewind(obj.offsetParent, false);
        }
        this.rewind(obj, true);
    }
    function resizeDiv() {
        var target = document.getElementById('target');
        pos = new AbsPos(target);
        target.style.width = document.body.clientWidth - pos.left - 10 ;
    }
    window.onresize = resizeDiv;
    window.onload = resizeDiv;
    </script>
</head>
<body>
    <div nowrap id="target" style="height:100px; overflow-x: scroll">
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />
    </div>
</body>
</html>

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

photo
admin