ページに関するTips


・ページインジケータ

NN2No good NN3OK NN4OK MozillaOK IE3No good IE4OK

この Tips集のようにブラウザを Frame で分割し、 左をメニュー・右をメインにした構成のページは結構多いと思われます。

この構成のページの場合、 メニューのリンクをクリックしてメインに本文を表示するが一般的ですが、 本文が似通った構成である場合には、 現在表示している本文がどのメニューで表示されているものかわからなくなることがあります。

この様な場合の改善策としては、 選択された項目がオープン状態のメニューを用意しておき、 選択された時に本文とメニュー(時には Frame も)を更新する方法があります。

この方法は複数のメニューを用意するので、 本文表示の際のセッション数が増えるデメリットがあります。

JavaScriptを利用した例としては、 選択中の本文を Frame の親ドキュメントに設定しておき、 メニュー表示時に JavaScript で全ての項目を表示する方法があります。

この例としては、この Tips集の「フォルダー型階層メニュー」がありますが、 項目をクリックする度にメニューの再表示を行なう必要があります。

ここで紹介する方法は、構成が変更されないメニューで、 項目がクリックされた場合に、選択項目の一部(イメージ)を変更することで、 現在表示中の本文をページの再表示なしに変更する方法です。

以下に、親ドキュメントを Frame.htm、メニューを Contents.htm、 本文を Doc.htm として、そのコードを示します。

Frame の親( Frame.htm )

<head>
    :
<script language="JavaScript"><!--
curName = '';           // 現在表示中の項目名
loaded  = false;        // メニューのロード状態

// 表示中ドキュメント状態変更用中継関数
function chgImage(nm){
  if (loaded) window.contents.openDoc(nm);
  else        curName=nm;
}
// --></script>
</head>
<frameset cols="20%,*" border=0 frameborder=no framespacing=0>
  <frame name="contents" src="Contents.htm">
  <frame name="doc"      src="Doc.htm">
</frameset>

メニュー( Contents.htm )

<head>
    :
<script language="JavaScript"><!--
// ダミー関数
function init(){}
function activate(nm,dir){}
function openDoc(nm){}
// --></script>
<script language="JavaScript1.1"><!--
activeName    = '';            // 現在マウスが触れている項目

// アイコン画像の定義
unselectImage = 'UCLOSED.gif'; // マウスが触れていない場合
selectImage   = 'CLOSED.gif';  // マウスが触れている場合
openImage     = 'OPEN.gif';    // 本文が表示中の場合

// パフォーマンス対策用
unselectImg = new Image(); unselectImg.src=unselectImage;
selectImg   = new Image(); selectImg.src  =selectImage;
openImg     = new Image(); openImg.src    =openImage;

// アイコン画像を変更する関数
function setImage(nm,imgno){
  var img=unselectImg.src;
  if(imgno==1)      img=selectImg.src;
  else if(imgno==2) img=openImg.src;
  eval('document.'+nm).src=img;
}

// 本文表示時のアイコン画像更新関数
function openDoc(nm){
  if(parent.curName!='' && nm!=parent.curName){
    if(activeName==parent.curName) setImage(parent.curName,1);
    else                           setImage(parent.curName,0);
  }
  parent.curName=nm;
  if(nm!='') setImage(parent.curName,2);
}

// メニュー用 HTML のローディング完了時の処理
function init(){
  parent.loaded = true;
  if(parent.curName!='') openDoc(parent.curName);
}

// マウス移動時のアイコン画像更新関数
function activate(nm,dir){
  if(nm!=activeName){
    if(activeName!='' && activeName!=parent.curName)
      setImage(activeName,0);
    activeName=nm;
  }
  if(activeName == parent.curName) setImage(nm,2);
  else if(dir)                     setImage(nm,1);
  else                             setImage(nm,0);
  if(!dir) activeName='';
}
// --></script>
</head>
<body ... onLoad="init();">
    :
<a href="Doc.htm" target="doc"
   onMouseOver="activate('Doc',true );"
   onMouseOut ="activate('Doc',false);"
   ><img name="Doc" src="UCLOSED.gif" border=0
   >ドキュメント1</a>
    :

本文( Doc.htm )

<body ...
      onLoad="if(parent.chgImage) parent.chgImage('Doc');">

この文字の部分は必要に応じて修正します。

フレームの HTML では FRAMESET でページをレイアウトするとともに、 状態表示を行うフレーム( メニュー )の名称に chgImage 関数の contents を変更します。

メニュー側では unselectImage, selectImage, openImage 変数で定義している画像を使用する画像に変更します。
※ これらの画像は全て同じサイズの画像にします。

状態表示を行う部分ではマウスが触れたとき表示変更するなら、 onMouseOver, onMouseOut イベントで activate 関数を呼び出します。
activate 関数の引数は以下の通りです。
※ アイコン画像は最初に unselectImg で定義した画像にします。

activate( nm, dir )
nm  : 変更するアイコン画像に付けた名称( name属性 )
dir : 表示方向
      true  = selectImg で定義した画像を表示
      false = unselectImg で定義した画像を表示

状態表示の対象となるドキュメント( 本文 )では BODY部の onLoad イベントで、 parent.chgImage 関数を呼び出します。

もし、本文がフレームの子としてではなく、単独で表示される可能性があるなら、 if(parent.chgImage) で判定しておくと良いでしょう。
chgImage の引数は以下の通りです。

chgImage( nm )
nm  : 変更するアイコン画像に付けた名称( name属性 )

使用例

このコードの表示サンプルは こちら です。


注意事項

NN2 IE3
JavaScript1.0 では image オブジェクトの操作ができないので、 この機能は実現できません(コードでは無処理になります)。 このバージョンのブラウザを考慮する場合には、 unselectImage に指定するイメージを機能が無効の場合でも ある程度見栄えのするものにした方が良いでしょう。

IE3
IE3 には JavaScript1.1 と指定してあっても実行してしまうものがあります。 このスクリプトはそのようなブラウザを考慮していません。 もし、そのようなバージョンでも動作する必要があるなら、 ブラウザの種別とバージョンを判定して イメージオブジェクトへのアクセスを無効化する処理を入れる必要があります。
IE4
このサンプルは onLoad イベントを使用していますので、 当然 Mac版 IE4.5 では動作しません。

もし、Mac版 IE4.5 でも動作するようにしたいなら、 気の進まない方法ですが、本文( Doc.htm )を以下のようにします。

interval = 1000; // 監視間隔( msec )
tid      = null; // タイマ識別子
function Mac4_5CacheBugFix(scr){
  if(   document.all && !document.getElementById
     && navigator.userAgent.indexOf('Mac')!=-1)
    tid = setTimeout(scr,interval);
}
function init(pageId){
  if(parent.chgImage){
    Mac4_5CacheBugFix('init("'+pageId+'")');
    parent.chgImage(pageId);
  }
}
<body ... onLoad="init('Doc');">

上の interval は必要に応じて適当に調整します。

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