Cross Browser のための DHTML


・スクロールウィンドウ

外部ファイル( HTML )をページ内に表示する場合、 IE なら IFRAME タグを使用すれば良いのですが、 NN4 では DIV( Layer )タグになります。

また、IFRAME を使用すると指定したサイズ以上のドキュメントの場合は スクロールバーが表示されますが表示位置が指定領域内であるためになかなかうまくできません。 それに、味も素っ気もないスクロールバーのデザインをページに合わせて変えることもできません。

一方、NN4 ではスクロールバーすら表示しないため、両方で通用するページを作成することは 結構難しい問題にもなります。

これらの問題に対するクロスブラウザ的解決は自作スクロールウィンドウです。 f(^^;

上のサンプルは「ライブラリ集」の「外部参照レイア」関連関数と「汎用イベントハンドラ」、 「スライダオブジェクト」を組み合わせて作成した例です。

残念ながら、このスクリプトは汎用と言えるコードは殆どありません。

親HTML用関数

divOnLoad    =null;     // ロード時に呼び出す関数
divNameOnLoad=null;     // ロードする HTML の識別子

// 外部参照ファイル用 onLoad 定義関数
function setOnLoadEvent(nm,fnc){
  divOnLoad    =fnc;
  divNameOnLoad=nm;
}

// onLoad イベントハンドル関数
function callOnLoadEvent(nm){
  if(nm==divNameOnLoad) divOnLoad();
}

子HTML用関数


// onLoad 通知関数
function subInit(id){
  if(window.callOnLoadEvent)                     // NN4
    callOnLoadEvent(id);
  else if(parent && parent.callOnLoadEvent)      // IE,NN6
    parent.callOnLoadEvent(id);
}

この関数は外部ファイルの情報を取り出すためのタイミングを通知する関数で、 呼び出し形式は見たとおり(笑)ですが、一応以下に示しておきます。

親HTML用関数
  外部参照ファイル用 onLoad 定義関数
    - 外部ファイルのロード完了時に呼び出す関数を登録します
    setOnLoadEvent(nm,fnc);
      nm  : 子HTMLの識別子
      fnc : ロード完了時に呼び出す関数
            fnc の呼び出し形式は以下の通り
              func();

  onLoad イベントハンドル関数
    - 外部ファイルのロード処理が完了したことを通知します
    callOnLoadEvent(nm);
      nm  : ロードした HTML の識別子

子HTML用関数
  onLoad 通知関数
    - ロード処理が完了したことをロード元に通知します
    subInit(nm);
      nm  : ロードした HTML の識別子

つまり、外部ファイルのロードを指示する時に setOnLoadEvent でロード時に呼び出す関数を登録し、 子HTMLファイルの onLoad 処理で subInit 関数を呼び出すと、 callOnLoadEvent を経由して登録した関数が呼び出されます。

この登録した関数で子HTMLファイルのサイズ等必要な情報を取り出して スライダなどの制御すれば良いわけです。


作り方

例えば、位置(200,100)にサイズ(200,100)の表示領域と、 その右に幅 16pixel のスクロールバーを表示するスクロールウィンドウを作るには 以下のようにします。

<style type="text/css"><!--
/* スクロールバー領域 */
#bar   { position:absolute;
  width:16; height:100;
  left:400; top:100; clip:rect(0 16 100 0);
  background-color:#eeeeee; layer-background-color:#eeeeee;
}
/* スクロールボタン */
.arrow { position:absolute; width:16; height:16; }
#up    { left:400; top:100; } /* 上 */
#down  { left:400; top:184; } /* 下 */
/* スライダ */
#slider{ position:absolute;
  width:16; height:16;
  left:400; top:116;
}
--></style>
<script language="JavaScript"><!--
exDiv       = null;  // 外部参照レイア
sdv         = null;  // スライダオブジェクト
loadExl     = false; // 子ファイルロード完了フラグ
scrTid      = null;  // スクロールタイマ
scrInterval = 100;   // スクロールインターバル

// 初期化関数
function init(){
  var div;

  // 上スクロールボタンにドラッグハンドラを付ける
  div=getDivFromName('up');
  ech_attachMouseDrag(div,
     scroll,1,null,null,scroll,0,null,null)
    .linkCtrl(getDivImage(div,'upb'));

  // 下スクロールボタンにドラッグハンドラを付ける
  div=getDivFromName('down');
  ech_attachMouseDrag(div,
     scroll,2,null,null,scroll,0,null,null)
    .linkCtrl(getDivImage(div,'downb'));

  // 外部参照レイアを生成する
  setOnLoadEvent('exl',loadedExt);
  exDiv=createExLayer('sub1.htm',200,100,200,100);
  setDivVisibility(exDiv,true);
}
// ロード完了処理
function loadedExt(){
  var exh=getExlHeight(exDiv);
  if(sdv==null){
    // スライダオブジェクトを生成する
    var div=getDivFromName('slider');
    sdv=Slider(div,1,52,0,exh-100,0,
               null,null, slideVCB,exDiv, null,null)
              .linkCtrl(getDivImage(sldDiv,'sd'));
  } else {
    // スライダの位置を初期位置に戻す
    sdv.slideTo(0);
    sdv.max=exh-100;
  }
  // スクロール位置を先頭に戻す
  scrollExlVItTo(exDiv,0);
  loadExl = true;
}
// スライド処理
function slideVCB(ctrl,exdiv,value){
  scrollExlVItTo(exdiv,parseInt(value));
}
// スクロールボタン処理
function scroll(ctrl,client){
  if(scrTid){ clearTimeout(scrTid); scrTid=null; }
  if(sdv && loadExl){
    var dy=0;
    switch(client){
    case 1: dy=-20; break;
    case 2: dy= 20; break;
    }
    if(dy!=0) doScroll(dy);
  }
}
// スクロール処理
function doScroll(dy){
  if(sdv && loadExl){
    sdv.slideBy(dy);
    scrTid=setTimeout('doScroll('+dy+')',scrInterval);
  }
}
// 表示ファイル切り替え処理
function loadExt(url){
  loadExl=false;
  changeExlURL(exDiv,url);
}
// 終了処理
function closure(){
  if(scrTid){ clearTimeout(scrTid); scrTid=null; }
}
// --></script>
<body ... onLoad="init();" onUnload="closure();">

<div id="bar"></div>
<div class="arrow" id="up">
  <img name="upb" id="upb" src="up.gif">
</div>
<div class="arrow" id="down">
  <img name="downb" id="downb" src="down.gif">
</div>
<div id="slider">
  <img name="sld" id="sld" src="slider.gif">
</div>

例によってこの文字の部分は「ライブラリ集」か または「汎用イベントハンドラ」「スライダ」で紹介している関数です。 スクリプト上には記述されていませんので、 使用する際にはそれらの項目を参照して追加してください。

また、この文字の部分はこのサンプル特有の部分です。 必要に応じて、またはページデザインに応じて変更してください。

スクロールボタンやスライダは予めスタイルシートを用いてレイアウトしていますが 各部品毎に配置するのではなく、全体を画像にして クライアントサイドイメージマップにした方がラクかもしれません。

スライダオブジェクトの生成は初回のファイルのロード完了時に loadedExt 関数内で行っていますが、 スライダの取りうる範囲はロードの度にロードしたドキュメントの高さに設定しています。 この範囲は実際には常にスクロール領域に表示される部分がありますので

ドキュメントの高さ - スクロール領域の高さ

になることに注意して下さい。

また、スクロールボタンの処理はボタンクリックではなく、汎用イベントハンドラを使用して mouseup から mousedown の間に srcInterval( 100msec )間隔でスクロール処理しています。 この1回のスクロールはこのサンプルでは 20pixel にしていますが、適当に調整して下さい。
また、このサンプルスクリプトでは loadExt 関数は定義のみで使用していませんが、 この関数は表示中の HTML を切り替える関数です。何らかの操作をきっかけにして、 切り替えたい url を指定して、この関数を呼び出すと表示内容が切り替わります。


注意事項


Copyright(c) 1998 - 2001 ShinSoft. All rights reserved.