セレクトメニューの選択項目に応じて、もう1つのセレクトメニュ



0   名前: ルーク : 2007/03/30(金) 08:36  ID:KsHciFfq sub-gI
セレクトメニューの選択項目に応じて、もう1つのセレクトメニューの内容を変更するにはどのようにしたらいいでしょうか?

【何をしたいのか】
→三つのセレクトボックスをつかい条件を絞り込むような
選択をしていきたいと考えています。
EX}
三つのセレクトボックスは 会社名 路線 駅名
実行すると
JR東→ 中央線→ 荻窪駅

【現在の状況】
→ どこがどううまくいかないのか、何がわからないのか、などを具体的に記入してください。

【何をしてみたのか】
スレッドNo. 869 三次元配列について
http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi?mode=view&no=869
を参考に三次元配列にしたらどうかと考えてみましたがわかりませんでした。

【備考】
JavaScript例文辞典
http://www.openspc2.org/reibun/javascript/form_selectmenu/027/index.html
を利用しまして三つのセレクトボックスを使うことは出来るようになりました。
<html>
<head>
<title>セレクトメニューの選択項目に応じて、もう1つのセレクトメニューの内容を変更する(可変)</title>
<script language="JavaScript"><!--
menuItem = [	["MZ-80K","MZ-700","MZ-2500"],
			["PC-6001","PC-8001","PC-8801","PC-9801","PC-9821"],
			["FM-8","FM-7","FM-11","FM-77AV"] ];
function setMenuItem(n)
{
	len = document.myForm.Computer.options.length;
	for (i=len-1; i>=0; i--)
	{
		document.myForm.Computer.options[i] = null;
	}
	for (i=0; i<menuItem[n].length; i++)
	{
		document.myForm.Computer.options[i] = new Option(menuItem[n][i],menuItem[n][i]);
	}
}
// --></script>


<script language="JavaScript"><!--
menuItem2 = [	["1","2","3"],
			["4","5","6","7","8"],
			["9","10","11","12"] ];
function setMenuItem2(n)
{
	len = document.myForm.aaa.options.length;
	for (i=len-1; i>=0; i--)
	{
		document.myForm.aaa.options[i] = null;
	}
	for (i=0; i<menuItem2[n].length; i++)
	{
		document.myForm.aaa.options[i] = new Option(menuItem2[n][i],menuItem2[n][i]);
	}
}
// --></script>

</head>
<body>
<form name="myForm">
<select name="Maker" onChange="setMenuItem(this.selectedIndex)">
<option value="SHARP">SHARP</option>
<option value="NEC">NEC</option>
<option value="FUJITSU">FUJITSU</option>
</select>

<select name="Computer" onChange="setMenuItem2(this.selectedIndex)">
<option value="MZ-80K">MZ-80K</option>
<option value="MZ-700">MZ-700</option>
<option value="MZ-2500">MZ-2500</option>
</select>

<select name="aaa">
<option value="aa">aa</option>
<option value="bb">bb</option>
<option value="cc">cc</option>
</select>


</form>
</body>
</html>

アドバイスを頂けたらと思います。
よろしくお願いいたします。


1   名前: 元帥 : 2007/03/30(金) 08:36  [URL]  ID:4R.eWW5n sub-bK
メーカーから機種名を選ぶ部分までは完成していますね。
早川電機の場合、三機種だけですので、更に絞り込む場合も問題ありません。
が、日本電気と富士通は選択内容によっては、存在しない配列を指す事になり、エラーとなります。
なので、menuItem2の配列を増やせばエラーはなくなります。

# 結局、何をしたいのかイマイチ分からない…。
# 社名→機種 の結びつきは分かりますが、三つ目のselectとの関係が不明です。
# メーカーに関わらず、一番上の機種を選べば、三つ目のselectは1、2、3の選択肢になりますので。
# これは私の独り言なので、どーでもいい事ですが。


2   名前: 匿名 : 2007/03/30(金) 08:36  ID:6fAvcTJO sub-kJ
この手のスクリプトを見るたびに思うのだが、

(a). 非スクリプト環境はどうするの?
(b). 最終的にサーバに送るべきデータは何なの?

(a) に関して、もし何千件もの選択肢が複雑に絡み合うような要件であれば、サーバ側で対処すべきだろう。(b) に関して、最終的に不要なコントロールを「見た目」のためだけに置くのであれば、そもそもフォーム設計自体がおかしいということになる。

で、optgroup 要素の活用を考えてみた。

・最初にコントロールの連動関係の順番を定義しておく。
・選択した option 要素のラベルと同じ label 属性を持つ optgroup 要素を表示する。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>TEST</title>
<style type="text/css">

[disabled] {
  display: none;
}

</style>
<script type="application/javascript">

// コントロール関係の定義。
// 例えば、以下は 'input.data1'→'input.data2'→'input.data3' の順に絞り込む。
var RelationOrder = [ 'input.data1', 'input.data2', 'input.data3' ];

function filterSelects (select) {
    var form = select.form;
    var I = RelationOrder.length;
    var i = 0;
    
    // 現在のコントロールは関係的に何番目かを数える。
    while (i < I) if (RelationOrder[i++] == select.name) break;
    
    // 次のコントロール内容を絞り込む。
    filterOptions (form.elements[ RelationOrder[i++] ],
                   select.options[ select.selectedIndex ].text);
    
    // それ以降のコントロールをリセットする。
    while (i < I) {
        filterOptions (form.elements[ RelationOrder[i++] ], '');
    }
}

function filterOptions (select, label) {
    // 指定したラベルを持つ optgroup 要素のみ有効にする。
    var optgroup = select.getElementsByTagName ('optgroup');
    
    for (var i = 0, I = optgroup.length; i < I; i++) {
        optgroup[i].disabled = (optgroup[i].label != label);
    }
    select.selectedIndex = 0;
}

// フォーム初期化
addEventListener ('load', function () {
        filterSelects (document.forms[0].elements[ RelationOrder[0] ], '');
    }, false);

</script>
<form action="#">
  <p>
    <select name="input.data1" onchange="filterSelects (this); ">
      <option>-</option>
      <option>SHARP</option>
      <option>NEC</option>
      <option>FUJITSU</option>
    </select>
    <select name="input.data2" onchange="filterSelects (this); ">
      <option>-</option>
      <optgroup label="SHARP">
        <option>MZ-80K</option>
        <option>MZ-700</option>
        <option>MZ-2500</option>
      </optgroup>
      <optgroup label="NEC">
        <option>PC-6001</option>
        <option>PC-8001</option>
        <option>PC-9801</option>
        <option>PC-9821</option>
      </optgroup>
      <optgroup label="FUJITSU">
        <option>FM-8</option>
        <option>FM-7</option>
        <option>FM-11</option>
        <option>FM-77AV</option>
      </optgroup>
    </select>
    <select name="input.data3">
      <option>-</option>
      <optgroup label="MZ-700">
        <option>あいうえお</option>
        <option>かきくけこ</option>
      </optgroup>
      <optgroup label="PC-9801">
        <option>さしすせそ</option>
        <option>たちつてと</option>
      </optgroup>
      <optgroup label="FM-77AV">
        <option>なにぬねの</option>
      </optgroup>
    </select>
  </p>
  <script type="application/javascript">

document.write ('<p>JavaScript による選択肢の絞り込みを行っています。'
  + 'もしも不具合が生じる場合、JavaScript 機能をオフにして下さい。'
  + 'そうすれば確実にデータを送信することができます。</p>');

  </script>
</form>

optgroup 要素の disabled 属性に対応しているブラウザのみ。え、IE 対応? ソンナノヒツヨウデスカ?

3   名前: 匿名 : 2007/03/30(金) 08:36  ID:6fAvcTJO sub-kJ
一応 IE 対応版。Safari は、cloneNode したフォームのコントロールが elements で参照できないというバグにより対象外。スクリプトが動作しなくても、項目の選択自体はできるから、実用上は無問題だろう。たぶん。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>TEST</title>
<script type="text/javascript">

var RelationOrder = [ 'input.data1', 'input.data2', 'input.data3' ];
var OriginalForm;

onload = function () {
    OriginalForm = document.forms[0].cloneNode (true);
    filterSelects (document.forms[0].elements[ RelationOrder[0] ], '');
};

function filterSelects (select) {
    var form = select.form;
    var I = RelationOrder.length;
    var i = 0;
    while (i < I) if (RelationOrder[i++] == select.name) break;
    
    var clone = recoverControl (form, RelationOrder[i++]);
    filterOptions (clone, select.options[ select.selectedIndex ].text);
    
    while (i < I) {
        var clone = recoverControl (form, RelationOrder[i++]);
        filterOptions (clone, '');
    }
}

function filterOptions (select, label) {
    var optgroup = select.getElementsByTagName ('optgroup');
    
    // 指定ラベルと一致しない optgroup を削除する
    for (var i = 0, I = optgroup.length, n = i; i < I; i++) {
        if (optgroup[n].label != label) {
            select.removeChild (optgroup[n]);
        } else n++;
    }
    select.selectedIndex = 0;
}

function recoverControl (form, name) {
    // オリジナルのコントロールを復元する
    var clone = OriginalForm.elements[name].cloneNode (true);
    form.elements[name].parentNode.replaceChild (clone, form.elements[name]);
    return clone;
}

</script>
<body><!-- IE は、body 要素の開始タグがないと、body 開始直後の要素の範囲がバグる -->
<form action="#">
  <p>
    <select name="input.data1" onchange="filterSelects (this); ">
      <option>-</option>
      <option>SHARP</option>
      <option>NEC</option>
      <option>FUJITSU</option>
    </select>
    <select name="input.data2" onchange="filterSelects (this); ">
      <option>-</option>
      <optgroup label="SHARP">
        <option>MZ-80K</option>
        <option>MZ-700</option>
        <option>MZ-2500</option>
      </optgroup>
      <optgroup label="NEC">
        <option>PC-6001</option>
        <option>PC-8001</option>
        <option>PC-9801</option>
        <option>PC-9821</option>
      </optgroup>
      <optgroup label="FUJITSU">
        <option>FM-8</option>
        <option>FM-7</option>
        <option>FM-11</option>
        <option>FM-77AV</option>
      </optgroup>
    </select>
    <select name="input.data3">
      <option>-</option>
      <optgroup label="MZ-700">
        <option>あいうえお</option>
        <option>かきくけこ</option>
      </optgroup>
      <optgroup label="PC-9801">
        <option>さしすせそ</option>
        <option>たちつてと</option>
      </optgroup>
      <optgroup label="FM-77AV">
        <option>なにぬねの</option>
      </optgroup>
    </select>
  </p>
  <script type="text/javascript">

document.write ('<p>JavaScript による選択肢の絞り込みを行っています。'
  + 'もしも不具合が生じる場合、JavaScript 機能をオフにして下さい。'
  + 'そうすれば確実にデータを送信することができます。<\/p>');

  </script>
</form>

一覧へ戻る