WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:alertの有無の動作の違いについて

0:[投稿] ポコ [2003/04/23 18:27 ][環境:IE4以上 UNIX]

 はじめまして、ポコと申します。
リストにある項目を選択し、その項目をまとめて移動させる処理を作成していました。
移動自身は、問題なく動作するのですが、移動した先に表示位置を合わせる事ができません。
selected = true を指定すれば表示位置に移動するハズなのですが..(IEのみである事は承知しています。)
色々と試行錯誤をしている中で、下記alertを有効にすれば動作する事に気づきました。
なぜこの様な現象が発生するのでしょうか?またどのようにすれば、希望する動作をするのでしょうか?
 申し訳ありませんが、わかる方ご返答ください。

以下、長いですが現象を確認できるサンプルを作成しました。

<html>
<script language="JavaScript1.2">
function SelText()
{
   var Scroll = document.test.sel;
   var i=0;
   var i2=0;
   var cnt = 0;
   idx = Scroll.selectedIndex;

   if( idx == -1 ){
       alert( "項目を指定してください" );
       return;
   }else{
       var sel_arr = new Array();
       var nsel_arr = new Array();
       var idx = 0;
       var len = 0;
       var sel_cnt = 0;
       var nsel_cnt = 0;

       idx = Scroll.selectedIndex;
       len = Scroll.length;
       for( i=0; i<len; i++ )
       {
           if( Scroll.options[i].selected )
           {
               sel_arr[ sel_arr.length ] = Scroll.options[i].text;
           }else{
               nsel_arr[ nsel_arr.length ] = Scroll.options[i].text;
           }
       }
       Scroll.options.length = 0;
       for(i=0; i<nsel_arr.length; i++ )
       {
           cnt = Scroll.options.length++;
           Scroll.options[cnt].text = nsel_arr[i].toString();
       }
       for(i=0; i<sel_arr.length; i++ )
       {
           cnt = Scroll.options.length++;
           Scroll.options[cnt].text = sel_arr[i].toString();
       }
   }
//alert( "!" );    ← このアラートを有効にすると動作する
   //選択されていた項目を反転
   for( i=0; i<Scroll.length; i++)
   {
       for( i2=0; i2<sel_arr.length; i2++ )
       {
           if( Scroll.options[i].text == sel_arr[i2].toString() )
           {
               Scroll.options[i].selected = true;
               break;
           }
       }
   }
}
</script>
<body>
<form name="test">
<select name="sel" size=10 MULTIPLE >
   <option>1
   <option>2
   <option>3
   <option>4
   <option>5
   <option>6
   <option>7
   <option>8
   <option>9
   <option>10
   <option>11
   <option>12
   <option>13
   <option>14
   <option>15
   <option>16
   <option>17
   <option>18
   <option>19
   <option>20
</select>
<input type="button" name="B_1" value="Push" onClick="SelText()">
</form>
</body>
</html>


1:[回答] おーなーしぇふ [2003/04/24 18:57 ]

>selected = true を指定すれば表示位置に移動するハズ
まずおさえておきたいのは、「ウィンドウの描画後に指定すれば移動する」という点。
この点を確認するためには次のテストを参考に。

//テスト用
function Test(){    //選択のテスト
    var Scroll = document.test.sel;
    Scroll.options[15].selected = true;
}

1)移動するケース
<script type="text/javascript" language="JavaScript">
//(中略)
window.onload = Test;    //ウィンドウロード後の呼び出し
</script>


2)移動しないケース
<body>
(中略)
<input type="button" name="B_1" value="Push" onClick="SelText();">
</form>

<script type="text/javascript" language="JavaScript">
Test();
</script>
</body>

2)ではウィンドウの描画前に関数を呼び出しているので、選択には成功するものの、移動はしていません。


さて本題ですが;
>なぜこの様な現象が発生するのでしょうか?
alertがない場合は、関数SelText()によるスクリプト内での処理結果は、スクリプトが終了するまでウィンドウには反映(再描画)されません。つまり、描画前に選択処理をしても移動しない、2)のケースと同じです。

一方、alertを挿入すると、alertを表示するためにいったん処理がスクリプト(エンジン)から、ディスプレイ(エンジン)へ移ります。表示後、再びスクリプトに戻るわけですが、その際ウィンドウが「再描画」されます。この時点で、SelText()の前半処理(並び替え)は反映(描画)されます。そこで後半の(選択)処理を開始するため、結果として1)同様、移動に成功するわけです。

※ちなみに同じことをalertではなくstatusで試すと移動しません。これはstatusの場合再描画には関係しないためです。


>またどのようにすれば、希望する動作をするのでしょうか?
並び替え結果を再描画後、選択処理すれば良いのですが、それにはタイマー処理を使うのが良いようです。

●(参考)時間がかかる操作中に表示を更新する
http://www.microsoft.com/japan/msdn/columns/dude/dude02262001.asp


具体的には以下のように。

var Chk = new Array();    //選択項目の番号を保存する配列
function ChkSelect(){
    var st = "";    //確認用
    var Scroll = document.test.sel;
    //選択されていた項目を反転
    for( var i in Chk )
    {
        st += Chk[i] + ", ";
        Scroll.options[Chk[i]].selected = true;
    }
    status = "配列Chkの内容確認:" + st;
}

function SelText()
{
    var Scroll = document.test.sel;
    var i=0;
    var i2=0;
    var cnt = 0;
    idx = Scroll.selectedIndex;

    if( idx == -1 ){
        alert( "項目を指定してください" );
        return;
    }else{
        var sel_arr = new Array();
        var nsel_arr = new Array();
        var idx = 0;
        var len = 0;
        var sel_cnt = 0;
        var nsel_cnt = 0;

        idx = Scroll.selectedIndex;
        len = Scroll.length;
        for( i=0; i<len; i++ )
        {
            if( Scroll.options[i].selected )
            {
                sel_arr[ sel_arr.length ] = Scroll.options[i].text;
            }else{
                nsel_arr[ nsel_arr.length ] = Scroll.options[i].text;
            }
        }
        Scroll.options.length = 0;
        for(i=0; i<nsel_arr.length; i++ )
        {
            cnt = Scroll.options.length++;
            Scroll.options[cnt].text = nsel_arr[i].toString();
        }
        
        Chk = new Array();//配列を初期化
        for(i=0; i<sel_arr.length; i++ )
        {
            cnt = Scroll.options.length++;
            Scroll.options[cnt].text = sel_arr[i].toString();
                
         //選択する配列番号を記録しておく
            Chk.push( cnt );
        }
    }
    //alert( Chk );    //← このアラートを有効にすると動作する
    setTimeout( "ChkSelect();", 1 );    //タイマー処理
    return;
}


その他、類似のケースについて参考まで。

●onClickイベントの発生について
http://www.ybi.co.jp/koike/qa2500/qa2876.htm
●RPGの戦闘シーンを作成したい
http://www.ybi.co.jp/koike/qa3000/qa3037.htm
●onBlurの発生タイミングについて
http://www.ybi.co.jp/koike/qa3000/qa3114.htm


2:[完了] ポコ [2003/04/25 11:30 ]

おーなーしぇふ様
alertの有無で動作が異なる事から、システムや画面制御の問題なのかなぁ、と漠然と考えていましたが、
おーなーしぇふ様の説明で理解できました。サンプルプログラムまで作成して頂き、感謝しております。
 プログラムの方は、教えて頂いた方法で動作するようになりました。

 丁寧で親切な返答を頂きまして、本当にありがとうございました。

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World