Form に関するTips


・リストのオプションを変更する

NN2Unknown NN3OK NN4OK MozillaOK IE3OK IE4OK

複数の選択肢から一つを選択する場合、 数が少なければ HTML文書上にリンクやラジオボタンなどで一覧形式にします。

表現するスペースが少なければリスト選択を使うこともあるでしょう。

然し、選択肢が数十にも及ぶとどちらの形式を使うにしても、 入力する側にとってみれば苦痛でしかありません。

このような場合には、もし、選択肢が何らかの階層を持っていれば 対話的に絞り込むようにした方が良いかもしれません。

ここに挙げる例は SELECT を利用したオプションの内容を対話的に変更する方法です。

#> オプションの変更は、JavaScript1.1以上のみを対象とするなら Option() オブジェクトの生成で比較的簡単に実現できますが、 ここで挙げる方法は JavaScript1.0 でも動作できるように工夫したものです。

共通関数

<script language="JavaScript"><!--
jsver=1.0;
ie=(navigator.appName=='Microsoft Internet Explorer');
// --></script>
<script language="JavaScript1.1"><!--
jsver=1.1;
if(ie && navigator.appVersion.substring(0,3)<4.0) jsver=1.0;
// --></script>
<script language="JavaScript"><!--
// ===============================
// オプション定義配列の作成
// function DefOptions(){
//     :// ******************************
//     :// ここにオプション内容を定義する
//     :// ******************************
// }
// ===============================
options   = new DefOptions(); // オプション定義配列
loadedOpt = 0;                // 現在選択中の配列要素番号
// ======================================================
// 各オプションの定義( 実体 )
function Opt(text,value){
  this.text  = text;
  this.value = value;
}
// オプション定義変更関数( 共通 )
function loadOption(obj,n){
  if(n<0 || n>=options.length){
    alert('loadOption: illeagal parameter('+obj.name+','+n+')');
    return;
  }
  if(jsver>1.0){
    var ot = obj.options;
    var os = options[n];
    ot.length = os.length;
    for (var i=0; i<os.length; i++)
      ot[i] = new Option(os[i].text,os[i].value,false,false);
    // 先頭のオプションを選択状態にする
    ot[0].selected=true;
  }
  loadedOpt = n;
}
// option タグ生成関数( JavaScript1.0用 )
function optionString(){
  var os = options[loadedOpt];
  var s = '';
  for (var i=0; i<os.length; i++){
    s += '<option value="'+os[i].value+'">'+os[i].text;
  }
  return s;
}
// --></script>

スクリプト内で定義されている関数の主な呼出形式を以下に示します。


// オプションの定義関数
new Opt( text, value );
text  : オプション表示文字列
value : オプション選択値( 文字列 )

この関数は SELECT タグの OPTION として表示する内容を定義するための オブジェクト( コンストラクタ )です。


// オプション定義変更関数
loadOption(obj,n);
obj : SELECTタグのオブジェクト
n   : 切り替えるオプション定義番号( options配列の要素番号 )

この関数は obj で指定した SELECTタグのオプションを、 n で指定した定義セットのものに変更します。


// option タグ生成関数
optionsString();
戻り値 : 表示する OPTIONタグ の文字列

この関数は JavaScript1.0 用の関数で、現在設定されているオプション定義セットの内容を OPTIONタグの文字列として生成します。


使用方法

HTML のページ構成は JavaScript1.1以降用では単一構成ですが、 JavaScript1.0 では SELECTタグの OPTION を動的に変更できないので フレーム構成にします。

これらの2種類の構成はブラウザ判別でページ自体を振り分けると楽なのですが、 メンテナンスを考えて、ここではページ構成自体動的に変更する例を紹介します。

JavaScript1.1用 & フレームの親

<script language="JavaScript"><!--
// ===============================
// オプションの定義 (その1)
function PageTips(){
  var i=0;
  this[i++] = new Opt('フェードイン/アウト',    '11');
  this[i++] = new Opt('前のページに戻る',       '12');
      :
  this[i++] = new Opt('しおり',                 '19');
  this.length = i;
  return this;
}
// オプションの定義 (その2)
function DecorTips(){
  var i=0;
  this[i++] = new Opt('Whats New',              '21');
  this[i++] = new Opt('スクロールメッセージ',   '22');
      :
  this[i++] = new Opt('Whats New for you',      '25');
  this.length = i;
  return this;
}
// オプション定義配列の作成
function DefOptions(){
  var i=0;
  this[i++] = new PageTips();
  this[i++] = new DecorTips();
  this.length = i;
  return this;
}
// ===============================
options   = new DefOptions(); // オプション定義配列
   :
// 初期化関数( JavaScript1.1以降用 )
function init(){
  if (jsver>1.0){
    loadOption(document.f.s,loadedOpt);
    showValue(document.f.s,document.f.t,document.f.v);
  }
}
// オプション変更関数( JavaScript1.1以降用 )
function changeOpt(n,s,t,v){
  loadOption(s,n);
  showValue(s,t,v);
}
// 選択中のオプション内容表示関数( JavaScript1.1以降用 )
function showValue(obj,t,v){
  var o = obj.options[obj.selectedIndex];
  t.value = o.text;
  v.value = o.value;
}
// --></script>
</head>
<script language="JavaScript"><!--
if(jsver<1.1){
  // JavaScript1.0 ならフレーム構成にする
  document.write(
     '<frameset rows="100%,*" border=0>'
    +  '<frame name="fr" src="ChangeList10.htm">'
    +'<\/frameset>'
    );
} else {
  // JavaScript1.1以降なら BODY部を生成する
  document.write(
     '<body ... onLoad="init();">'
    +'<form name="f">'
    +'<input type="radio" name="r" value="0" '
    +    ' onClick="changeOpt(this.value,form.s,form.t,form.v)"'
    +    ' checked>Page Tips'
    +'<input type="radio" name="r" value="1" '
    +    ' onClick="changeOpt(this.value,form.s,form.t,form.v)"'
    +    '        >Decoration Tips'
    +'<br>'
    +'<select name="s" onChange="showValue(this,form.t,form.v)">'
    +  '<option value="-">------------------------'
    +  '<option value="-">------------------------'
    +  '<option value="-">------------------------'
    +  '<option value="-">------------------------'
    +  '<option value="-">------------------------'
    +'<\/select><br>'
    +'テキスト<input type="text" name="t" value="" size=30><br>'
    +'値      <input type="text" name="v" value="" size=10><br>'
    +'<\/form>'
    +'<\/body>'
    );
}
// --></script>
</html>

まず、オプションの定義を行います( この例では PageTips, DecorTips, DefOptions オブジェクト )。

各オプション定義のセット( PageTips, DecorTips )はオプション定義オブジェクト( Opt )の 配列で、DefOptions オブジェクトはこれらのセットの配列にします。

次に、JavaScript1.1以降用に初期化用の処理( この例では init関数 )と オプション変更処理( この例では changeOpt関数 )を定義します。

初期化処理は BODY部の onLoad イベントなどで行い、 初期状態で表示するリストのセット番号を指定して loadOption 関数を呼び出し、 SELECTタグ内のオプションを生成します。

オプション変更処理でも、変更するリストのセット番号を指定して loadOption 関数を呼出し、 オプションリストを変更します。

次に、HEAD部の後で、FRAMESET部 または BODY部 を生成します。

JavaScript1.0用には FRAMESETを出力します( ここで指定する HTML の内容は後述 )。
JavaScript1.1以降用には直接 BODY部を出力します。 出力する SELECTタグの OPTION には表示するリストの幅に合わせて、適当な文字列を指定し、 ドロップダウンリストの場合には表示したいリストの行数分だけ出力しておきます。

#> BODY部は document.writeしなくても直接記述しても動作するようですが、 FRAMESETとBODY部が混在する HTML は、その動作がブラウザ依存になるような気がするので オススメしません。 f(^^;

JavaScript1.0用に作成する FRAMESETの子の HTML は以下のようにします。

JavaScript1.0用( フレームの子 )

<head>
    :
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma"  content="no-cache">
    :
<script language="JavaScript"><!--
// オプション変更関数( JavaScript1.0用 )
function changeOpt(n,s,t,v){
  parent.loadOption(s,n);
  history.go(0);
}
// 選択中のオプション内容表示関数( JavaScript1.0用 )
function showValue(obj,t,v){
  if(parent.showValue) parent.showValue(obj,t,v);
}
// --></script>
</head>
<body>
    :
<script langauge="JavaScript"><!--
document.write(
   '<form name="f">'
  +'<input type="radio" name="r" value="0" '
  +    'onClick="changeOpt(this.value,form.s,form.t,form.v)" '
  +    (parent.loadedOpt=='0'?'checked':'')+'>Page Tips'
  +'<input type="radio" name="r" value="1" '
  +    'onClick="changeOpt(this.value,form.s,form.t,form.v)" '
  +    (parent.loadedOpt=='1'?'checked':'')+'>Decoration Tips'
  +'<br>'
  +'<select name="s" onChange="showValue(this,form.t,form.v)">'
  +  parent.optionString()
  +'<\/select><br>'
  +'テキスト<input type="text" name="t" value="" size=30>'
  +'値      <input type="text" name="v" value="" size=10>'
  +'<\/form>'
  );
showValue(document.f.s,document.f.t,document.f.v);
// --></script>
    :

JavaScript1.0 用の HTML では、リストの内容は history.go(0) によりリロードして表示します。 出力するオプションリストはフレームの親から optionString関数を呼び出して取得します。

リスト内容の変更には、フレームの親で定義している loadOption 関数を呼び出すことで行います。

#> history.go(0) でリロードするとブラウザのキャッシュ制御により 内容が変わらない場合が考えられます( NN2 も IE3 もないので未確認です f^^; )。

その場合は、この例のように HTML の先頭で Expires, no-cache 指定などにより キャッシュしないようにしておきます( 効果の程も未確認です f(^^;;; )。

このコードを用いたサンプルはこちらです。


注意事項

IE3
Microsoft Internet Explorer3.0 では history.go(0); を実行した場合、 「移動」メニューには現われませんが、 履歴が更新されるためオプションを切替えると「戻る」メニューで戻る時 何回も同じページが表示されます。

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