none
html/Javascript。RadioButtonのchecked=trueにするだけのコード。Edgeでの挙動が変。 RRS feed

  • 質問

  • html/Javascriptの質問です。宜しくお願い致します。

    --- Source ここから---

    <!DOCTYPE html>
    <html><head>
    <meta charset="utf-8">
    <title>Javascript Training</title>
    </head>
    <body>
    <form id="set" name="form">
        <input name="selectr" type="radio" value="12h">12h
        <input name="selectr" type="radio" value="24h">24h
        <!--<input name="selectr" type="radio" value="24h" checked="checked">24h -->
    </form>

    <script type="text/javascript">
    var elem = document.getElementById("set");
    var radioNodeList = elem.selectr;

    //document.write("selected = "+radioNodeList.value+". "); //radioNodeList.valueはEdgeでは効かない
    radioNodeList[1].checked = true;
    document.write("[0] = " + radioNodeList[0].checked);
    document.write(", [1] = " + radioNodeList[1].checked);
    </script>
    </body>
    </html>

    --- Source ここまで---

    上記のファイルをEdgeで開くと、radioNodeList[1]("24h")が選択状態です。ところがリロード(1度目)をすると何故かチェックが外れ無選択状態になり、何とさらに2度目のリロードをすると再び"24h"が選択状態となります。無選択状態と選択状態を交互に繰り返します。Chrome/Opera/Firefoxはキチンと動作し、その動作を見るとそちらが普通だと思えます。Edgeの動作は挙動が理解出来ません。それとも再現できませんでしょうか?

    Chrome/Opera/FirefoxではCookieを使いきちんと動くアプリが完成しています。IEは諦めていますが、Edgeは行けそうだと思って、バグ探しに最終版をひとつ一つ分解して取り出し検証・絞り込みを行ったところこのソースに行き着きました。

    全くのドツボです。何か抜けていますでしょうか?宜しくお願い致します。




    2018年11月8日 7:48

回答

  • ご返信ありがとうございます。

    ご提示されたコードでの問題点は、

    var elem = document.getElementById("set");
    var radioNodeList = elem.selectr; 

    上記のコードが、DOM の構築前に呼び出されてしまう可能性がある点です。つまりコントロール類 selector などの準備が完了する前にコードが呼び出される可能性があるので、その場合は、radioNodeList[1].checked = true; としても画面上に反映されないということが起こりえます。なので、window.onload イベントで呼び出される関数内で、document.getElementById を実行する必要があります。ちなみに私が試した全コードは以下です。

    <!DOCTYPE html>
    <html><head>
    <meta charset="utf-8">
    <title>Javascript Training</title>
    </head>
    <body>
    
    <form id="set" name="form">
        <input name="selectr" type="radio" value="12h">12h
        <input name="selectr" type="radio" value="24h">24h
    </form>
    
    <script type="text/javascript">
    function load() {
    	var elem = document.getElementById("set");
    	var radioNodeList = elem.selectr;
    	radioNodeList[1].checked = true;
    	var str = "[0] = " + toString.call(radioNodeList[0]);
    	str += ", [1] = " + toString.call(radioNodeList[1]);
    	alert(str);
    }
    window.onload = load;
    </script>
    
    </body>
    </html>
    • 回答としてマーク HISSTORY_T 2018年11月10日 16:02
    2018年11月10日 14:12

すべての返信

  • body タグ内の末尾に script タグを書いたとしても、その javascript 実行時に DOM の構築が完了していないことがあるようです。DOM の構築が完了した後に javascript を実行するには、window.onload イベントで javascript を実行するのが確実だと思います。

    https://developer.mozilla.org/ja/docs/Web/API/GlobalEventHandlers/onload

    追伸:
    他のソフト等が入っていない素の環境(Windows 10 x64, ver 1803)で再現し、javascript の実行タイミングを window.onload イベントに移すことで現象が解消されたため上記コメントを書いております。

    2018年11月8日 8:03
  • > 上記のファイルをEdgeで開くと、radioNodeList[1]("24h")が選択状態です。ところがリロード(1度目)をすると何故かチェックが外れ無選択状態になり、何とさらに2度目のリロードをすると再び"24h"が選択状態となります。無選択状態と選択状態を交互に繰り返します。

    同じコードで確認しましたが再現しません。何度リロードしても元のまま(以下の画像のまま)変わりません。環境は Windows 10 Pro 64-bit バージョン 1809、Edge 44.17763.1.0 です。

    キャッシュの問題とかはないですか? 以下の Fiddler の画像のように毎回要求が出て応答が返ってきてますか?

    2018年11月8日 9:28
  • 返信ありがとうございます。そして有用なソフトのご紹介感謝いたします。
    Fiddlerをインストールし、勉強しながら使っています。(アドウェアらしきものの活動も複数視覚化されて。このソフトでひょっとしたら分かるかな?タッチキーボードですが、SHIFTを使って選択などを行っているとSHIFTが押されっぱなしになってしまう)。

    本題ですが、304になっています、何度押してもです。ステータスコードが、304 Not Modifiedということはキャッシュを表示しているということになるのでしょうか?

    どう対処したらよいかご指導願います。

    あと、こちらの環境は、x64 Windows 10 Home Version 1803, 42.17134.1.0, EdgeHTML 17.17134.
    です。アップデートの仕方が見つかりません。
    2018年11月10日 7:02
  • > 304になっています、何度押してもです。ステータスコードが、304 Not Modifiedということはキャッシュを表示しているということになるのでしょうか?

    そのとおり、キャッシュから取得してます。

    リロードする前にブラウザのキャッシュを消去してください。Edge なら、たぶん、Fiddler で消去できると思いますので試してみてください。



    > あと、こちらの環境は、x64 Windows 10 Home Version 1803, 42.17134.1.0, EdgeHTML 17.17134.
    です。アップデートの仕方が見つかりません。

    それは本題とは関係ないと思います。アップデートの仕方は別途 Community などで質問してください。
    2018年11月10日 8:11
  • ありがとうございます。再現されているんですね。やはりそうですか。(何故か今、Edgeの開発者ツールが開けません)。

    僕のコードが間違っているのでしょうか、かなり手こずっています。最終型のコードと相談ですが、どこだったかonloadを使い分けて複数実行できるコードがありましたよね。

    追伸:コードで教えてくださいませんか?うまくいかない僕のコードは、

    --- Source 始め ---

    <!DOCTYPE html>
    <html><head>
    <meta charset="utf-8">
    <title>Javascript Training</title>
    <script></script>
    </head>
    <body>
    <form id="set" name="form">
        <input name="selectr" type="radio" value="12h">12h
        <input name="selectr" type="radio" value="24h">24h<br>
        <button id="reloadbtn" onclick="reload()">reload from server?</button>
        <button id="reloadbtn2" onclick="reload2()">reload</button>
    </form>

    <script type="text/javascript">
    var elem = document.getElementById("set");
    var radioNodeList = elem.selectr; 

    window.onload = chkdtrue(radioNodeList); //何故かradioNodeListがグローバル変数でない

    function chkdtrue(radioNodeList){
    radioNodeList[1].checked = true;
    document.write("[0] = " + radioNodeList[0].checked);
    document.write(", [1] = " + radioNodeList[1].checked);
    }

    function reload(){
    location.reload(true);
    }

    function reload2(){
    location.reload();
    }

    </script>
    </body>
    </html>



    --- Source 終わり ---

    宜しくお願い致します。


    2018年11月10日 9:53
  • ご返信ありがとうございます。

    ご提示されたコードでの問題点は、

    var elem = document.getElementById("set");
    var radioNodeList = elem.selectr; 

    上記のコードが、DOM の構築前に呼び出されてしまう可能性がある点です。つまりコントロール類 selector などの準備が完了する前にコードが呼び出される可能性があるので、その場合は、radioNodeList[1].checked = true; としても画面上に反映されないということが起こりえます。なので、window.onload イベントで呼び出される関数内で、document.getElementById を実行する必要があります。ちなみに私が試した全コードは以下です。

    <!DOCTYPE html>
    <html><head>
    <meta charset="utf-8">
    <title>Javascript Training</title>
    </head>
    <body>
    
    <form id="set" name="form">
        <input name="selectr" type="radio" value="12h">12h
        <input name="selectr" type="radio" value="24h">24h
    </form>
    
    <script type="text/javascript">
    function load() {
    	var elem = document.getElementById("set");
    	var radioNodeList = elem.selectr;
    	radioNodeList[1].checked = true;
    	var str = "[0] = " + toString.call(radioNodeList[0]);
    	str += ", [1] = " + toString.call(radioNodeList[1]);
    	alert(str);
    }
    window.onload = load;
    </script>
    
    </body>
    </html>
    • 回答としてマーク HISSTORY_T 2018年11月10日 16:02
    2018年11月10日 14:12
  • ありがとうございました。無事動きました。ドツボだったのは何故かEdgeはリロードを押しても変更が反映されないことが多々あるようです(キャッシュを読み込むため)。Edgeブラウザを一度閉じて開き直さないと反映させられない。これを知らないと何度ソースコードを変更しても変わらないと右往左往することになります。
    さらに朗報です。IE11でも動作しました。kenjinoteさんありがとうございました。そして、SurferOnWwwも感謝申し上げます。


    2018年11月10日 16:16
  • .html ページを作って検証してみたところ、自分の環境 Windows 10 Pro 64-bit バージョン 1809、Edge 44.17763.1.0 でも、

    1 回目のリロードでラジオボタンのチェックが外れる、2 回目のリロードで元の通りチェックが入る、以降その繰り返し

    ・・・という問題を再現できました。キャッシュを削除してからリロードしても問題は再現できるということで、ブラウザのキャッシュは関係ないようです。

    でも原因が分かりません。

    kenjinote さんが言われる、

    > 上記のコードが、DOM の構築前に呼び出されてしまう可能性がある点です。

    ではなさそうです。

    自分が試した限り、質問者さんのコードの、

    radioNodeList[1].checked = true;
    document.write("[0] = " + radioNodeList[0].checked);
    document.write(", [1] = " + radioNodeList[1].checked);

    で期待される結果になりますので、関係する要素全ての DOM の構築は window.onload を待たずに完了しているはずです。

    radioNodeList[1].checked = true; でラジオボタン表示にチェックが入らないという見かけの問題のようです。

    DOM が取得できていることを分かりやすくするため、質問者さんのコードを以下のように変更して試してみました。

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        </head>
    <body>
        <form>
            <input name="selectr" id="radio1" type="radio" value="12h" />12h
            <input name="selectr" id="radio2" type="radio" value="24h" />24h
            <br />
            <span id="span1" />
        </form>
    
        <script type="text/javascript">
            var r1 = document.getElementById("radio1");
            var r2 = document.getElementById("radio2");
            var s = document.getElementById("span1")
            r2.checked = true;
            var str = "12h = " + r1.checked;
            str += ", 24h = " + r2.checked;
            s.textContent = str;
        </script>
            
    </body>
    </html>

    F12 開発者ツールのデバッガでブレークポイントを設定してリロードしてみます。下の画像の赤丸がブレークポイントで、そこで止まった時点でラジオボタン要素の DOM は取得できてます。さらに矢印のコードまでステップ実行して str を見ると 2 つ目のラジオボタンにコード上ではチェックが入っているのが分かります。

    しかしながら、Edge の画面に表示される結果は以下の通り、ラジオボタンのチェックは外れています。

    理由が分かりません。もう少し調べてみますが、今日はギブアップ。理由が分かる方がおられましたら教えていただけると幸いです。

    ちなみに、最初の私のレスで試したのは、ブラウザがキャッシュから取得するのを避けるため .aspx ページを使いました。でもキャッシュは上に述べたように関係なかったです。

    違いは応答ヘッダだけなのですか。

    .aspx

    HTTP/1.1 200 OK
    Cache-Control: private
    Content-Type: text/html; charset=utf-8
    Server: Microsoft-IIS/10.0
    X-AspNet-Version: 4.0.30319
    X-Powered-By: ASP.NET
    Date: Sun, 11 Nov 2018 03:21:58 GMT
    Content-Length: 768
    
    
    <!DOCTYPE html>
    
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>
    
    </title></head>
    <body>
        <form>
            <input name="selectr" id="radio1" type="radio" value="12h" />12h
            <input name="selectr" id="radio2" type="radio" value="24h" />24h
            <br />
            <span id="span1" />
        </form>
    
        <script type="text/javascript">
            var r1 = document.getElementById("radio1");
            var r2 = document.getElementById("radio2");
            var s = document.getElementById("span1")
            r2.checked = true;
            var str = "12h = " + r1.checked;
            str += ", 24h = " + r2.checked;
            s.textContent = str;
        </script>
    
    </body>
    </html>

    .html

    HTTP/1.1 200 OK
    Content-Type: text/html
    Last-Modified: Sun, 11 Nov 2018 03:15:00 GMT
    Accept-Ranges: bytes
    ETag: "53266ebb6c79d41:0"
    Server: Microsoft-IIS/10.0
    X-Powered-By: ASP.NET
    Date: Sun, 11 Nov 2018 03:23:50 GMT
    Content-Length: 787
    
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        </head>
    <body>
        <form>
            <input name="selectr" id="radio1" type="radio" value="12h" />12h
            <input name="selectr" id="radio2" type="radio" value="24h" />24h
            <br />
            <span id="span1" />
        </form>
    
        <script type="text/javascript">
            var r1 = document.getElementById("radio1");
            var r2 = document.getElementById("radio2");
            var s = document.getElementById("span1")
            r2.checked = true;
            var str = "12h = " + r1.checked;
            str += ", 24h = " + r2.checked;
            s.textContent = str;
        </script>
            
    </body>
    </html>



    • 編集済み SurferOnWww 2018年11月11日 5:11 訂正
    2018年11月11日 5:06
  • 気がつかないで御免なさい。ありがとうございます。

    なんて言いましょう、抽象的な表現は無意味でしょうが、敢えて言うと"更新ボタンが壊れている"としか言いようがないです。

    2018年11月16日 13:48
  • レスを有難うございます。

    依然として原因不明ですが、先の私のレス以降分かったことを含めて、まとめておきますと:

    (1) 問題が起こるのは Edge のみで、IE11, Chrome, Firefox, Opera, Safari では期待通り JavaScript が働いて何度リロードを繰り返しても常にチェックが入ります。

    (2) 最初の質問にあったソースコードの JavaScript のコードの位置で、JavaScript が実行される時には DOM の構築は完了しているはず(実際、getElementById によってすべての要素のオブジェクトを取得できる。window.onload を待つ必要はない)。

    (3) ラジオボタンだけでなくチェックボックスも同様で、リロードするたびチェック有無が繰り返されます。

    (4) input type="text" の value 属性や select/option の selected 属性の JavaScript による同様な設定は、リロードを繰り返しても期待通り設定が反映されます。

    (5) checked 属性の設定の取得のタイミングによって結果が異なります。例えば以下のようなコードで、

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
    </head>
    <body>
        <form>
            <input id="Radio1" name="radio1" type="radio" value="radiobuttonValue" />
            <input id="Checkbox1" name="checkbox1"type="checkbox" value="checkboxvalue"/>
            <br />
            <span id="span1"></span>
            <br />
            <span id="span2"></span>
        </form>
    
        <script type="text/javascript">
            var rbn = document.getElementById("Radio1");
            var cbx = document.getElementById("Checkbox1");
            var spn1 = document.getElementById("span1");
            var spn2 = document.getElementById("span2");
    
            rbn.checked = true;
            cbx.checked = true;
    
            spn1.textContent = "radiobutton checked: " + rbn.checked + ", checkbox checked: " + cbx.checked;
    
            window.onload = function () {
                spn2.textContent = "radiobutton checked: " + rbn.checked + ", checkbox checked: " + cbx.checked;
            }
        </script>
            
    </body>
    </html>

    初期画面の表示後、最初のリロードで以下の結果となります。



    取得した checked 属性の値が、設定直後と window.onload のタイミングで異なることに注目してください。

    以上の結果からの想像ですが、奇数回のリロードの時は、checked 属性については、DOM とスクリプトがシンクロしないということのように見えます。

    原因・理由は上にも書きましたが不明です。バグか仕様か Microsoft に聞かないと分からないかもしれませんね。

    ここでこの話をいつまでも引っ張っても何ですので、ここらで止めておきます。もし、はっきりしたことが分かったら追記します。



    • 編集済み SurferOnWww 2018年11月17日 6:16 訂正
    2018年11月17日 3:17