Cross Browser のための DHTML


・Popup表示オブジェクト

レイアを表示する場合、リンク文字や画像をクリックして単に表示することが多いですが、 表示過程を表現してみるのも良いかもしれません。


outline

technique

Popup オブジェクトは2つのレイアの表示を切替えるオブジェクトです。

切替えは一方のレイアを非表示にして、他方を表示状態にするまでの間に 一方のレイアから他方のレイアまでの位置とサイズを結ぶ途中経過のレイアを表示して行います。

技術的にはこのオブジェクトは2つのレイアと、 その表示切替え過程を表示する1つのレイアで構成され、 過程を表示するレイアのリサイズと位置制御を行うオブジェクトです。

上のサンプルは2つのレイアの表示制御する PopupWin オブジェクトのサンプルです。

アイコンをクリックするとアニメーションしながらウィンドウを表示します。 「outline」アイコンの方は 1フレームで表示し、 「technique」アイコンの方は 5フレームで表示します。

以下は PopupWin オブジェクトのコードです。

<script language="JavaScript1.2"><!--
_cascadeWin = null; // 途中経過用レイア
// ポップアップウィンドウオブジェクト
function PopupWin(id,iconDiv,winDiv,nproc,interval){
  this.id          = id;
  if(_cascadeWin==null){
    _cascadeWin = createLayer(0,0,10,10);
    setDivBackgroundColor(_cascadeWin,'#cccccc');
  }
  this.cascadeDiv  = _cascadeWin;
  this.iconDiv     = iconDiv;  this.winDiv      = winDiv;
  this.interval    = interval; this.timeId      = null;
  this.nproc       = nproc;    this.cproc       = 0;
  this.iconDisable = true;
  this.dx = 0; this.dy = 0; this.dw = 0; this.dh = 0;
}
// ポップアップメソッド( 開始 )
PopupWin.prototype.popup = function(){
  if(this.timeId) clearTimeout(this.timeId);
  this.timeId    = null;
  var cascadeDiv = this.cascadeDiv;
  var winDiv     = this.winDiv, iconDiv    = this.iconDiv;
  this.dx = (getDivLeft  (winDiv)-getDivLeft  (iconDiv))
          / this.nproc;
  this.dy = (getDivTop   (winDiv)-getDivTop   (iconDiv))
          / this.nproc;
  this.dw = (getDivWidth (winDiv)-getDivWidth (iconDiv))
          / this.nproc;
  this.dh = (getDivHeight(winDiv)-getDivHeight(iconDiv))
          / this.nproc;
  this.cproc = this.nproc;
  moveDivTo  (cascadeDiv,
              getDivLeft (iconDiv),getDivTop   (iconDiv));
  resizeDivTo(cascadeDiv,
              getDivWidth(iconDiv),getDivHeight(iconDiv));
  setDivVisibility(cascadeDiv,true);
  if(this.iconDisable) setDivVisibility(iconDiv,false);
  if(!this.popupProcessCB ||
      this.popupProcessCB(this,this.popupProcessCD)){
    this.timeId = setTimeout(this.id+'.doPopupProcess();',
                             this.interval);
  } else {
    setDivVisibility(cascadeDiv,false);
    setDivVisibility(winDiv,true);
  }
}
// ポップアップメソッド( 実行 )
PopupWin.prototype.doPopupProcess = function(){
  this.timeId = null;
  var cascadeDiv = this.cascadeDiv;
  moveDivBy(cascadeDiv,this.dx,this.dy);
  resizeDivBy(cascadeDiv,this.dw,this.dh);
  if(--this.cproc>0){
    if(!this.popupProcessCB ||
        this.popupProcessCB(this,this.popupProcessCD)){
      this.timeId = setTimeout(this.id+'.doPopupProcess();',
                               this.interval);
    } else {
      setDivVisibility(cascadeDiv,false);
      setDivVisibility(this.winDiv,true);
    }
  } else {
    setDivVisibility(this.winDiv,true);
    setDivVisibility(cascadeDiv,false);
    if(this.popupCompleteCB)
      this.popupCompleteCB(this,this.popupCompleteCD);
  }
}
// ポップダウンメソッド( 開始 )
PopupWin.prototype.popdown = function(){
  if(this.timeId) clearTimeout(this.timeId);
  this.timeId = null;
  var iconDiv = this.iconDiv, winDiv = this.winDiv,
      cascadeDiv = this.cascadeDiv;
  this.dx = (getDivLeft  (iconDiv)-getDivLeft  (winDiv))
          / this.nproc;
  this.dy = (getDivTop   (iconDiv)-getDivTop   (winDiv))
          / this.nproc;
  this.dw = (getDivWidth (iconDiv)-getDivWidth (winDiv))
          / this.nproc;
  this.dh = (getDivHeight(iconDiv)-getDivHeight(winDiv))
          / this.nproc;
  this.cproc = this.nproc;
  moveDivTo  (cascadeDiv,
              getDivLeft (winDiv),getDivTop   (winDiv));
  resizeDivTo(cascadeDiv,
              getDivWidth(winDiv),getDivHeight(winDiv));
  setDivVisibility(cascadeDiv,true);
  setDivVisibility(winDiv,false);
  if(!this.popdownProcessCB ||
      this.popdownProcessCB(this,this.popdownProcessCD)){
    this.timeId = setTimeout(this.id+'.doPopdownProcess();',
                             this.interval);
  } else {
    setDivVisibility(cascadeDiv,false);
    if(this.iconDisable) setDivVisibility(iconDiv,true);
  }
}
// ポップダウンメソッド( 実行 )
PopupWin.prototype.doPopdownProcess = function(){
  this.timeId = null;
  var cascadeDiv = this.cascadeDiv;
  moveDivBy  (cascadeDiv,this.dx,this.dy);
  resizeDivBy(cascadeDiv,this.dw,this.dh);
  if(--this.cproc>0){
    if(!this.popdownProcessCB ||
        this.popdownProcessCB(this,this.popdownProcessCD)){
      this.timeId = setTimeout(this.id+'.doPopdownProcess();',
                               this.interval);
    } else {
      setDivVisibility(cascadeDiv,false);
      if(this.iconDisable) setDivVisibility(this.iconDiv,true);
    }
  } else {
    if(this.iconDisable) setDivVisibility(this.iconDiv,true);
    setDivVisibility(cascadeDiv,false);
    if(this.popdownCompleteCB)
      this.popdownCompleteCB(this,this.popdownCompleteCD);
  }
}
// 表示過程取り消しメソッド
PopupWin.prototype.cancelProcess = function(){
  if(this.timeId) clearTimeout(this.timeId);
  this.timeId = null;
}
// 進行コールバック登録メソッド
PopupWin.prototype.setProcessCallback
                   = function(upcb,upcd, pdcb,pdcd){
  this.popupProcessCB   = upcb;
  this.popupProcessCD   = upcd;
  this.popdownProcessCB = pdcb;
  this.popdownProcessCD = pdcd;
}
// 完了コールバック登録メソッド
PopupWin.prototype.setCompleteCallback
                   = function(upcb,upcd, pdcb,pdcd){
  this.popupCompleteCB   = upcb;
  this.popupCompleteCD   = upcd;
  this.popdownCompleteCB = pdcb;
  this.popdownCompleteCD = pdcd;
}
// --></script>

この文字の部分は「ライブラリ集」で紹介している関数です。 上のスクリプトでは記述されていませんので、 使用する際には「ライブラリ集」を参照して追加してください。

また、この文字の部分は途中経過表示用のレイアの配色で、 気にいらなければ適当に修正してください(笑)。

PopupWin オブジェクトのメソッドとプロパティを以下に示します。

コンストラクタ
  new PopupWin(id,iconDiv,winDiv,nproc,interval);
    id       : 生成したオブジェクトを格納する変数の名称
    iconDiv  : アイコンとして登録するレイア
               注) document オブジェクトの直接の子
    winDiv   : ポップアップするウィンドウとして登録するレイア
               注) document オブジェクトの直接の子
    nproc    : 途中経過を表示する時のフレーム数
    interval : 途中経過の表示更新間隔( msec )

進行コールバック登録メソッド
  - 表示更新する度に呼び出す関数を登録します
  setProcessCallback(upcb,upcd, pdcb,pdcd);
    upcb : ポップアップ中に呼び出す関数( 不要時は null )
    upcd : upcb で指定した関数を呼び出す際に付けるデータ
    pdcb : ポップダウン中に呼び出す関数( 不要時は null )
    pdcd : pdcb で指定した関数を呼び出す際に付けるデータ

完了コールバック登録メソッド
  - 表示動作完了時に呼び出す関数を登録します
  setCompleteCallback(upcb,upcd, pdcb,pdcd);
    upcb : ポップアップ完了時に呼び出す関数( 不要時は null )
    upcd : upcb で指定した関数を呼び出す際に付けるデータ
    pdcb : ポップダウン完了時に呼び出す関数( 不要時は null )
    pdcd : pdcb で指定した関数を呼び出す際に付けるデータ

ポップアップメソッド( 開始 )
  - ポップアップ表示動作を開始します
  popup();

ポップダウンメソッド( 開始 )
  - ポップダウン表示動作を開始します
  popdown();

表示過程取り消しメソッド
  - 動作中の表示処理を中止します
  cancelProcess();

使い方

アイコン用レイア( id="icon1"、位置[50,100] )とウィンドウ用レイア( id="win1"、位置[200,100] )を ポップアップさせる場合には以下のようにします。

<style type="text/css"><!--
/* アイコンの表示スタイルの定義 */
DIV.icon  { position:absolute; text-align:center; }
#icon1    { width:48; height:32; }
FONT.icon { background-color:black; padding:2px; }
A.icon    {
  text-decoration:none;
  font-size:12px; font-weight:600; color:#ffffcc;
}
/* ウィンドウの表示スタイルの定義 */
DIV.win   { position:absolute; visibility:hidden;
  font-size:14px;
}
#win1     { width:200;
  background-color:#cccccc; layer-background-color:#cccccc;
}
--></style>
<script language="JavaScript"><!--
pw1       = null; // PopupWin オブジェクト
pInterval = 50;   // インターバル( msec )
n_frames  = 5;    // フレーム数

// 初期化処理
function init(){
  pw1 = new PopupWin('pw1',
              initDivPos(initDivSize(getDivFromName('icon1'))),
              initDivPos(initDivSize(getDivFromName('win1' ))),
              n_frames,pInterval);
}
// 終了処理
function closure(){ if(pw1) pw1.cancelProcess(); }
// --></script>
</head>
<body ... onLoad="init();" onUnload="closure();">
   :
<!-- アイコンの定義 -->
<div class="icon" id="icon1">
  <a class="icon" href="javascript:void(0);"
     onClick="if(pw1) pw1.popup(); return false;">
    <img src="icon.gif" border=0 width=32 height=32><br>
    <font class="icon">outline</font>
  </a>
</div>
<!-- ウィンドウの定義 -->
<div class="win" id="win1">
  <table border=1 cellspacing=2 cellpadding=5 width=200>
  <tr><td bgColor="#ffffee">
    <p>
      ウィンドウ<br>
      <a href="javascript:void(0);"
            onClick="if(pw1) pw1.popdown();return false;">
         閉じる
      </a>
    </p>
  </td></tr></table>
</div>
   :

この文字の部分はこのサンプル特有の部分です。

アイコン、ウィンドウ用レイアの定義は absolute なものであれば良いので、 ページに合わせてデザインします。

このサンプルでは 各レイアの位置は絶対座標で定義していますが、 ブラウザのウィンドウサイズに合わせて JavaScript で配置するなら visibility を hidden に しておくと良いでしょう。

また、レイアの定義を HTML で直接レイアを書いていますが、 もし旧バージョンでも見られるようにする必要があるなら onLoad イベント以降に バージョン判定をして動的に生成すると良いかもしれません。

ポップアップさせるための初期化処理は、単にオブジェクトを生成しているだけですが、 もし、途中経過表示時に何らかの処理をするなら setProcessCallbak メソッドで処理を定義したり デモ用スクリプトのようにウィンドウの Z オーダを制御するなら setCompleteCallback メソッドで 定義します。

ポップアップ、ダウン動作は初期化処理完了後に popup, popdown メソッドを呼び出すだけです。


注意事項

<!-- Mac OS X版 IE5.12 対策の例 -->

<style type="text/css"><!--
      :
/* 途中経過用レイアの定義 */
#cascadeWin{ position:absolute;
  width:10px; height:10px;
  color:#cccccc;
}
--></style>
<script language="JavaScript1.2"><!--
    :
// ポップアップウィンドウオブジェクト
function PopupWin(id,iconDiv,winDiv,nproc,interval){
  this.id          = id;
  if(_cascadeWin==null){
    _cascadeWin = getDivFromName('cascadeWin');
  }
      :
}
      :
// --></script>
<body ...>
    :
<div id="cascadeWin"></div>
    :

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