chihiro1364
@chihiro1364

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

質問です。

ボタンを押したときの動作についての疑問。
nextSiblingプロパティは具体的に選択したノードのどこから見て、ノードのどこを戻り値にしているのか。

HTMlで作った、
チェックボックスにチェックを入れると、以下の全てのチェックボックスにチェックが付き、
チェックを入れるとチェックボックス横の文字列も伴って変わるテスト構文をしました。

結果的にはうまくいったのですが、なぜこの構文でうまくいくのか不明です。
最初に載せたjs構文が自分の思うようにうまくいった時の構文ですが、
途中にある、
「checkall.nextSibling.textContent = "チェックを外す"」
と、
「checkall.nextSibling.textXContent = "すべてをチェック"」
部分にtextContentが無いとなぜチェックを付けたり外したりした時にチェックボックスが付いてこないのか。
"hoge"idを取得してtextContentプロパティに文字列を代入しても同じ結果にならないのはなぜか?
が全く不明です。

なぜnextSiblingにtextContentを付けないとチェックボックスはついてこないのかを教えてください。

HTML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <mata charset="utf-8">
        <title>タグ属性によるイベントハンドラ登録サンプル</title>
    </head>
    <body>
        <p>
            <label id="hoge"><input type="checkbox" id="checkall" name="checkall" value="1" onclick="onCheckallChanged()">すべてをチェック</label>
            <hr>   
            <label><input type="checkbox" name="skill" value="1">HTTML</label><br>
            <label><input type="checkbox" name="skill" value="2">JavaScript</label><br>
            <label><input type="checkbox" name="skill" value="3">PHP</label><br>
            <label><input type="checkbox" name="skill" value="2">SQL</label><br>
        </p>
        <script type="text/javascript" src="1Ans.js"></script>
    </body>
</html>

自分の思うようにうまくいったjs構文

function onCheckallChanged() {
    let checkall = document.getElementById("checkall");
    if (checkall.checked) {
        checkall.nextSibling.textContent = "チェックを外す"
    } else {
        checkall.nextSibling.textContent = "すべてをチェック"
    }
    let checkboxes = document.getElementsByName("skill");
    for (let i = 0; i < checkboxes.length; i++) {
        checkboxes[i].checked = checkall.checked;
    }
}

自分がこれでもうまくいくと思ったjs構文(チェックボックス無表示で文字列のみ反映)

function onCheckallChanged() {
    let checkall = document.getElementById("checkall");
    let hoge = document.getElementById("hoge");
    if (checkall.checked) {
        hoge.textContent = "チェックを外す"
    } else {
        hoge.textContent = "すべてをチェック"
    }
    let checkboxes = document.getElementsByName("skill");
    for (let i = 0; i < checkboxes.length; i++) {
        checkboxes[i].checked = checkall.checked;
    }
}

又、自分はnextSiblingプロパティを理解していないせいもあると思うので、
具体的には選択したノードのどこから見た時のどのノードの事を指しているのかも教えてください。

お願い致します。

0

5Answer

余計な一言かもしれませんが・・・

HTMLを普通に書くとどうしても改行・インデントが多くなりますが、
それらもテキストノードになってします。

// ブラウザのコンソールで確かめてみてください
console.log(document.body.childNodes);

previousSiblingnextSiblingは(HTMLElementに限らない)Nodeを返しますが、
返値がHTMLElementのpreviousElementSiblingnextElementSiblingもあるので、使い分けられると便利かと思います。

2Like

Comments

  1. @chihiro1364

    Questioner

    いえ、普通に書いたhtmlにjs実装してたらどこかでエラー起きてたと思うので重宝する知識になります。
    ありがとうございます。

どちらかといえばnextSiblingでなくtextContentの解釈の問題です。
HTMLをツリーにしてみると(<p>以下

  • label[id="hoge"]
  • input[id="checkall"]
  • #TEXTNODE "すべてをチェック"
  • hr
  • label
  • input
  • br
  • label
  • input
  • br
  • label
  • input
  • br
  • label
  • input
  • br

nextSiblingは「次(隣)のノード」を表すので、checkall.nextSiblingは#TEXTNODE(テキストノード)でなります。
textContentに文字列を代入するとそのノードの中身を代入した文字列(テキストノード)に置き換えますので以下のようになります。

// 「#TEXTNODE "すべてをチェック"」が「#TEXTNODE "チェックを外す"」に置き換わる
checkall.nextSibling.textContent = "チェックを外す"
// <input>と「#TEXTNODE "すべてをチェック"」が「#TEXTNODE "チェックを外す"」に置き換わる
hoge.textContent = "チェックを外す"

1Like

Comments

  1. @chihiro1364

    Questioner

    回答頂き有難う御座います!

    すみません。
    前提知識としてnextSibringは読み込みのみ出来て値を代入出来ないのを知りませんでした。

    では、
    チェックボックスにチェックが入ったら、
    チェックボックスの表示と一緒に文字列を変える為の構文が、
    checkall.nextSibling.textContent=

    じゃ無いければならないのは何ででしょうか?
    なぜ、

    checkall.textContent=

    だとチェックボックスは消えて文字列だけ更新されるのでしょうか?

    どうしてもnextSiblingが関係している様に見えますが、根本的な仕組みが調べても出て来ません。
    どうか教えてください。

  2. まず前提として、チェックボックスとは`<input type="checkbox">`のことです。

    チェックボックスの「隣」のテキスト(テキストノード)を書き換えるのですから、
    `checkall.nextSibling.textContent = "・・・"`
    でなければいけません。

    `hoge.textContent = "・・・"`
    としてしまえばhogeの子孫要素全て(`<input>`も含めて)まとめて書き換えられてしまうので、チェックボックスが消えるというわけです。

    ※<input>は空要素なので`checkall.textContent`を使うことはありません(誤字だと思いますけど)。
  3. @chihiro1364

    Questioner

    有難うございます。

    `hoge.textContent = "・・・"`
    としてしまえばhogeの子孫要素全て(`<input>`も含めて)まとめて書き換えられてしまうので、チェックボックスが消えるというわけです。

    の文で理解出来ました。
    textContentプロパティはテキストのみ指定すると思い込んでた為、理解に時間がかかりました。

参考サイト

nextSiblingに関してこちらのサイト見れば分かりますか?
メロンとスイカの隙間です。
https://syncer.jp/Web/API_Interface/Reference/IDL/Node/nextSibling/

あなたがこれでもうまくいくと思ったらできなかったjs構文に関して

hoge.textContentは次が該当します。なので文字を転送するとcheckallが消えます。

<input type="checkbox" id="checkall" name="checkall" value="1" onclick="onCheckallChanged()">すべてをチェック

checkallをhogeから外に出せば、あなたがうまくいくと思った通り、hoge.textContentに文字を転送してもcheckallは消えず、文字だけ変わります。それはhoge.textContentに該当するのが"すべてをチェック"の部分になるからです。(個人的にはこれをおすすめしたい)

<input type="checkbox" id="checkall" name="checkall" value="1" onclick="onCheckallChanged()">
<label id="hoge" for="checkall">すべてをチェック</label>

あなたの思うようにうまくいったjs構文に関して

checkall.nextSibling.textContentはcheckallの終わりの">"から次のタグ"</label>"の間なので

すべてをチェック

が該当します。なので上手くいきます。

1Like

Comments

  1. @chihiro1364

    Questioner

    回答ありがとうございます。

    個人的にはnextとpreviousSiblingが理解の鬼門になっていたのですが、
    紹介して頂いたサイトで仕様がはっきり明記してたのでほぼ理解出来ました。

    ワガママになるかも知れませんが、教えて頂きたい事がもう一点。

    兄弟ノードが改行のエレメントオブジェクトに、nestSiblingを使ってコンソールに出力した際に、
    "#text"
    と現れて、内容を色々と含んでますが、これはどう言う意味なのでしょうか?

兄弟ノードが改行のエレメントオブジェクトに、nestSiblingを使ってコンソールに出力した際に、"#text"と現れて、内容を色々と含んでますが、これはどう言う意味なのでしょうか?

それはnodeNameです。
次の処理を実行してみてください

hogeのnodeNameはLABEL
checkallのnodeNameはINPUT
何もない場所は#text
です。


const hoge = document.getElementById("hoge");
console.log(hoge.nodeName); // LABEL
console.log(hoge.textContent);
console.log(hoge.nextSibling.nodeName); // #text
console.log(hoge.nextSibling.textContent);

const checkall = document.getElementById("checkall");
console.log(checkall.nodeName); // INPUT
console.log(checkall.textContent);
console.log(checkall.nextSibling.nodeName); //#text
console.log(checkall.nextSibling.textContent);

1Like

Comments

  1. @chihiro1364

    Questioner

    空白もひとまとまりのノードとして見られてるって事ですね。
    タグで囲まれた箇所のみ「ノード」と言えるものだと思ってました。

    ノードの概念が変わりました。
    ありがとうございます。

Your answer might help someone💌