堀北真希うさぎ
主な作品
制作者が作ったイラストと動画のサンプル

ページ案内

選択に応じてメニューやテキスト入力欄を切り替えるスクリプト。

選択に応じてメニューやテキスト入力欄を切り替えるスクリプト・目次。

選択に応じてメニューやテキスト入力欄を切り替えるスクリプトの概要。

メニューからの選択に応じてメニューとテキスト入力欄を切り替えるスクリプトです。

これに依り、状況に依りフォームの形を変えると言った複雑なフォームを実現する事が可能です。

まず言いたい事。

何度も書いておりますが、JAVAスクリプトは必須の技術ではないため、閲覧者の中には使えないように設定している者もいます。

このスクリプトの場合、非対応環境へはかなりの工夫が必要になるでしょう。

選択に応じてメニューやテキスト入力欄を切り替えるスクリプトのサンプル。

以下のフォームは、利用する列車を入力すると言うものです。

スクリプトを実行できる環境なら(ネットスケープは6.0以降、オペラは7.0以降)、列車の系統をラジオボタンで撰べるようになっております。

選択すると、それに応じてメニューが変わるのが分かります。

更に、在来線列車を表す「その他」を選択すると、列車名の入力欄が現れます。

ネットスケープ 3.x〜4.x及びオペラ 6.xでは、このような高度な操作が出来ないため、スクリプト対応となっていても、単純なメニューが表示されます。

但し、在来線列車を表す「その他」を選択すると、次の画面で列車名入力を行う事を知らせるようにしております。

一方スクリプトが実行出来ない環境でも、旧型ブラウザと同じ表示になりますが、不正な選択肢でもエラーになりません。

ご利用列車
  1. 列車名を選択して、列車番号を入力して下さい。

  2. 入力を確認して、送信ボタンを押してください。

メニューに応じてテキスト入力欄を変えるスクリプトの考え方。

まず、JAVAスクリプトではメニューを後から変える事は可能ですが、メニューをテキスト入力欄に変えたりするような事は出来ません。

このような事をするには、ダイナミックHTMLの技術を用いてメニューを非表示、テキストを表示などと言うような操作を行なわなければなりません。

ダイナミックHTMLはネットスケープ 4.x及びインターネットエクスプローラ4.x以降から利用可能になっておりますが、ネットスケープ 4.xでは実装が不充分なためこの機能を利用する事は難しい状況です。

また、オペラ 6.xでもダイナミックHTMLの一部が利用出来ません。

そこで、ネットスケープ 4.xなどの旧式ブラウザでは単純なメニューとして、新たなテキスト入力が必要な場合はCGIが次の画面を案内するようにすれば良い事にし、現行のCSS対応ブラウザでは表題のように動的にフォームを操作すると言うやり方を採る事にしました。

メニューに応じてテキスト入力欄を変えるスクリプトのソースとHTML文書での記述。

メニューに応じてテキスト入力欄を変えるスクリプトのソース。

メニューに応じてテキスト入力欄を変えるスクリプト「ChangeMenu2.js」「ChangeMenu2-2.js」は以下のようになっております。

「ChangeMenu2.js」のソース
NoDHTML=(!document.all && !document.getElementById) || (navigator.useAgent.indexOf('Opera/6.')>=0) || (navigator.useAgent.indexOf('Opera 6.')>=0);

function changeMenu2(n) {
    if (NoDHTML) return;
    if (n==100) {
        if (document.all) {
            document.all['TNAME'].style.display='none';
            document.all['TNAME2'].style.display='inline';
            }
        else if (document.getElementById) {
            document.getElementById('TNAME').style.display='none';
            document.getElementById('TNAME2').style.display='inline';
            }
        with(document.forms[0].TNAME) {
            options.length=1;
            options[0].text='列車名を入れて下さい';    options[0].value='';
            }
        document.forms[0].TNAME2.value='列車名を入れて下さい';
        }
    else {
        if (document.all) {
            document.all['TNAME2'].style.display='none';
            document.all['TNAME'].style.display='inline';
            }
        else if (document.getElementById) {
            document.getElementById('TNAME2').style.display='none';
            document.getElementById('TNAME').style.display='inline';
            }
        document.forms[0].TNAME2.value='';
        if (n==0) {
            with(document.forms[0].TNAME) {
                options.length=4;
                options[0].text='のぞみ';    options[0].value='nozomi';
                options[1].text='ひかり';    options[1].value='hikari';
                options[2].text='こだま';    options[2].value='kodama';
                options[3].text='つばめ';    options[3].value='tsubame';
                }
            }
        else if (n==1) {
            with(document.forms[0].TNAME) {
                options.length=5;
                options[0].text='はやて';    options[0].value='hayate';
                options[1].text='やまびこ';    options[1].value='yamabiko';
                options[2].text='なすの';    options[2].value='nasuno';
                options[3].text='つばさ';    options[3].value='tsubasa';
                options[4].text='こまち';    options[4].value='komachi';
                }
            }
        else if (n==2) {
            with(document.forms[0].TNAME) {
                options.length=3;
                options[0].text='とき';    options[0].value='toki';
                options[1].text='たにがわ';    options[1].value='tanigawa';
                options[2].text='あさま';    options[2].value='asama';
                }
            }
        else if (n==99) {
            with(document.forms[0].TNAME) {
                options.length=1;
                options[0].text='成田エクスプレス';    options[0].value='NEX';
                }
            }
        else {
            with(document.forms[0].TNAME) {
                options.length=1;
                options[0].text='********';    options[0].value='';
                }
            }
        }
    document.forms[0].TNAME.options[0].selected=true;
}

function checkEnter2() {
    if (!document.forms[0].TNAME.options[document.forms[0].TNAME.selectedIndex]) {
        alert('列車名が選択されておりません!'); return(false);
        }
    var i=document.forms[0].TNAME.options[document.forms[0].TNAME.selectedIndex].value;
    if (NoDHTML) {
        if (i=='') {
            alert('列車名が選択されておりません!'); return(false);
            }
        if (i!='?' && document.forms[0].tnumber.value=='') {
            alert('列車番号が入力されておりません!'); return(false);
            }
        if (i=='?') {
            alert('【ご案内】成田エクスプレス以外の在来線列車名は次の画面で入力して下さい。'); return(true);
            }
        return(true);
        }
    if (document.forms[0].TNAME.options[document.forms[0].TNAME.selectedIndex].value=='' &&
        (document.forms[0].TNAME2.value=='' || document.forms[0].TNAME2.value=='列車名を入れて下さい')) {
        alert('列車名が選択されておりません!'); return(false);
        }
    if (document.forms[0].tnumber.value=='') {
        alert('列車番号が入力されておりません!'); return(false);
        }
    return(true);
}

if (!NoDHTML) {
    document.write(
        '<p>ご乗車予定の列車を選択して下さい。</p>'+
        '<ul>'+
        '    <li><label><input type="radio" name="train" onclick="changeMenu2(0);" onkeypress="return(true)" selected="selected" />東海道・山陽・九州新幹線</label></li>'+
        '    <li><label><input type="radio" name="train" onclick="changeMenu2(1)" onkeypress="return(true)" />東北・山形・秋田新幹線</label></li>'+
        '    <li><label><input type="radio" name="train" onclick="changeMenu2(2);" onkeypress="return(true)" />上越・信越新幹線</label></li>'+
        '    <li><label><input type="radio" name="train" onclick="changeMenu2(99);" onkeypress="return(true)" />成田エクスプレス</label></li>'+
        '    <li><label><input type="radio" name="train" onclick="changeMenu2(100);" onkeypress="return(true)" />その他の在来線特急</label></li>'+
        '    </ul>'+
        '</li>'+
        '<li>'
        );
    }
「ChangeMenu2-2.js」のソース
ダイナミックHTMLに対応していない環境では意味の無い入力欄を書き出す処理だけですが、表示位置の都合で別スクリプトになっております。
if (!NoDHTML) {
    document.write(
        '<input type="text" name="TNAME2" id="TNAME2" value="" size="20" />'
        );
    }

メニューに応じてテキスト入力欄を変えるスクリプトを実行するHTML文書の記述。

一方、HTML文書側には、以下のように記述されております。

<body>要素開始タグ
<body onload="changeMenu2(-1);">
フォーム部分
ここでは、特にスクリプトが使えない場合のフォームを予め用意している事に注目して下さい。
<table class="forNN4" border="0" cellspacing="0" cellpadding="0" summary="この表はネットスケープ 4.xでの表示崩れ対策で導入されているものです。"><tbody><tr><td>
    <form action=" (略) " method="post" onsubmit="return(checkEnter2());">
        <fieldset>
            <legend>ご利用列車</legend>
            <ol>
                <li>
                    <script type="text/javascript" charset="shift_jis" src="ChangeMenu2.js"></script>
                    <p>列車名を選択して、列車番号を入力して下さい。</p>
                    <div>
                        <select name="TNAME" id="TNAME">
                                <option value="">【東海道・山陽・九州新幹線】</option>
                                <option value="nozomi">のぞみ</option>
                                <option value="hikari">ひかり</option>
                                <option value="kodama">こだま</option>
                                <option value="tsubame">つばめ</option>
                                <option value="">【東北・北海道・山形・秋田新幹線】</option>
                                <option value="hayate">はやて</option>
                                <option value="yamabiko">やまびこ</option>
                                <option value="nasuno">なすの</option>
                                <option value="tsubasa">つばさ</option>
                                <option value="komachi">こまち</option>
                                <option value="">【上越・信越新幹線】</option>
                                <option value="toki">とき</option>
                                <option value="tanigawa">たにがわ</option>
                                <option value="asama">あさま</option>
                                <option value="">【在来線列車】</option>
                                <option value="NEX">成田エクスプレス</option>
                                <option value="?">その他</option>
                                </select>
                        <script type="text/javascript" charset="shift_jis" src="ChangeMenu2-2.js"></script>
                        <input type="text" name="tnumber" value="" size="4" />号
                        </div>
                    </li>
                <li>
                    <p>入力を確認して、<samp>送信</samp>ボタンを押してください。</p>
                    <p><input type="submit" value="送信" /></p>
                    </li>
                </ol>
            </fieldset>
        </form>
    </td></tr></tbody></table>

スクリプトの構成。

このスクリプトは、以下のような仕組みになっております。

  1. <script>要素で呼出された「ChangeMenu2.js」は以下の処理を行います。
    1. 先ずメニューを切り替える函数changeMenu2()の定義を行ない、
    2. 続いて送信ボタンが押されたときに、正常な入力かどうかを確認する函数checkEnter2()の定義も行ない、
    3. スクリプトが使える環境でのみ使えるラジオボタンをHTML文書中(すなわち、フォームの内部)に書き込みます。
  2. もう一つの<script>要素で呼出された「ChangeMenu2-2.js」は、CSS対応環境(ネットスケープ 4.xを除く)でのみ意味のある列車名入力フォームを書き出しております。
  3. 読込が終わってから、<body>要素開始タグに書かれたonload属性で指定された函数「changeMenu2(-1)」を起動することで、スクリプトが使えない環境でのメニューを、スクリプトが使える環境でのものに書き換えてしまいます。

基本的な動作。

基本的には、選択に応じてメニューを変えるスクリプトと殆ど同じなので、そちらをご覧頂く事として、ここでは、フォームの表示の切り替えについて解説します。

フォームを出したり消したりする動作は、ダイナミックHTMLと呼ばれる技術が必要です。

具体的には表示させる可能性のあるフォームアイテムを予め用意し、適宜表示/非表示を切り替えると言う動作を行ないます。

尚、単純に表示を切り替えるだけでは、フォームが送り出すデータに影響を与える事は出来ませんので、適宜フォームの内容を修正する事になります。

事前処理…ダイナミックHTMLに対応していないブラウザかどうかを調べる。

まず、「ChangeMenu2.js」の一行目でダイナミックHTMLに対応していないブラウザかどうかを判定しております。

NoDHTML=(!document.all && !document.getElementById) || (navigator.useAgent.indexOf('Opera/6.')>=0) || (navigator.useAgent.indexOf('Opera 6.')>=0);
ダイナミックHTMLに対応していないブラウザかどうかを調べる部分の解説。

基本的にダイナミックHTMLはCSSのプロパティ操作であるため、CSSを実装していないブラウザでは動作しません。

また、ネットスケープ 4.xではダイナミックHTMLの仕様が不充分なため、やはり利用出来ません。

前半の「(!document.all && !document.getElementById)」は、ネットスケープ 4.x以外のCSS実装ブラウザである事をチェックしております。

後半の「(navigator.useAgent.indexOf('Opera/6.')>=0) || (navigator.useAgent.indexOf('Opera 6.')>=0)」はオペラ 6.xを弾くための措置です。

フォームアイテムの表示切替。

ダイナミックHTMLに関しての詳細は「ダイナミックHTML」をご覧頂く事として、ここでは簡単に説明しておきます。

ダイナミックHTMLでは、HTML文書中のオブジェクトを操作するのにid属性値で与えられたID名を利用します。

そこで、表示を切り替えたいフォームアイテムにはid属性を与えておく事になります。

このスクリプトでは、列車名を撰ぶメニューには「TNAME」、在来線列車の名前を直接入力する入力欄には「TNAME2」と言うIDを与えておきます。

さて、このようにIDを与えられたHTMLの要素は、ダイナミックHTMLに対応したブラウザ(ネットスケープ 4.xを除く)なら、そのCSSのプロパティ定義をスクリプトから切り替える事が可能になります。

CSSでは表示/非表示はdisplayプロパティで切り替えられますので、スクリプトでもそのように切り替えを行なっております。

具体的な処理は以下のようになっております。

    if (n==100) {
        if (document.all) {
            document.all['TNAME'].style.display='none';
            document.all['TNAME2'].style.display='inline';
            }
        else if (document.getElementById) {
            document.getElementById('TNAME').style.display='none';
            document.getElementById('TNAME2').style.display='inline';
            }
        with(document.forms[0].TNAME) {
            options.length=1;
            options[0].text='列車名を入れて下さい';    options[0].value='';
            }
        document.forms[0].TNAME2.value='列車名を入れて下さい';
        }
    else {
        if (document.all) {
            document.all['TNAME2'].style.display='none';
            document.all['TNAME'].style.display='inline';
            }
        else if (document.getElementById) {
            document.getElementById('TNAME2').style.display='none';
            document.getElementById('TNAME').style.display='inline';
            }
        document.forms[0].TNAME2.value='';
            (以下略)
フォームアイテムの表示切替の解説。

函数本体の「if (n==100)」と言うのは、ラジオボタンで「その他の在来線特急」を撰んだ際に成立するもので、この場合は列車名選択メニューは消して、代りに列車名入力欄を表示させます。

それ以外の場合h逆に列車名入力欄を非表示にして列車名選択メニューを表示させます。

これらの切り替えには、当該要素オブジェクトのCSSで言うdisplayプロパティを切り替えればいいので、そのようにしております。

尚、ダイナミックHTMLには、ネットスケープ 4.x独自仕様の他、インターネットエクスプローラ独自仕様とW3Cが策定した標準規格仕様があり、それぞれをチェックする事で対処しなければなりません。

具体的には、document.allオブジェクトが定義されている場合はインターネットエクスプローラ独自仕様に従って処理し、document.getElementByIdオブジェクトが定義されている場合は標準規格仕様に従って処理すれば良い訳です。

ダイナミックHTML非対応環境への配慮。

当たり前ですがダイナミックHTMLには対応していない環境もあります。

そのような環境では使えないと言うのは明らかに問題なので、非対応環境への配慮を行なう事となります。

具体的には、

ダイナミックHTMLが使えない環境で違和感の無いフォームを予め用意する。
ダイナミックHTMLが使えないと意味が無い入力欄やラジオボタンなどは、ダイナミックHTML非対応環境では出力しないようにします。
ダイナミックHTMLが使えない環境では切り替え処理をやり過ごすようにする。
ダイナミックHTMLが使えない環境で無理矢理実行させたらエラーで利用不能になるかも知れません。

そこで、

前者の「ダイナミックHTML非対応環境では何もせずに戻るようにする処理」は以下のようになります。

function changeMenu2(n) {
    if (NoDHTML) return;

一方、後者「ダイナミックHTML非対応環境に合わせた判定」は以下のようになります。

function checkEnter2() {
    if (!document.forms[0].TNAME.options[document.forms[0].TNAME.selectedIndex]) {
        alert('列車名が選択されておりません!'); return(false);
        }
    var i=document.forms[0].TNAME.options[document.forms[0].TNAME.selectedIndex].value;
    if (NoDHTML) {
        if (i=='') {
            alert('列車名が選択されておりません!'); return(false);
            }
        if (i!='?' && document.forms[0].tnumber.value=='') {
            alert('列車番号が入力されておりません!'); return(false);
            }
        if (i=='?') {
            alert('【ご案内】成田エクスプレス以外の在来線列車名は次の画面で入力して下さい。'); return(true);
            }
        return(true);
        }

以上のようにして、ダイナミックHTML非対応環境でも問題が起こらないようにします。

選択に応じてメニューやテキスト入力欄を切り替えるスクリプトの別解。

今回はフォームにダイナミックHTML対応環境向けの入力欄などを埋め込むやり方を採りましたが、他にも方法はあります。

実際のスクリプトは書きませんが、以下のようにしても良いでしょう。

  1. ダイナミックHTMLが使えない環境向けの入力フォーム甲にid属性でIDを付けておく。
  2. スクリプトはダイナミックHTMLが使える環境では、フォーム甲に対して「display: none」プロパティを与え、且つ専用のフォーム乙を代りに書き出して使う。

つまり、フォームをなるべく共用するのではなく、フォームを完全に分けてしまう訳です。

しらぎくのウェブサイト作成入門サイトマップ



marguerite.site@gmail.com