uhyohyo.net

JavaScript初級者から中級者になろう

二章第五回 木構造の操作:ノードの追加

今回は、前回とは逆に新しいノードを子に追加するということを解説します。

ノードを作る

まず、ノードを追加するには、追加するノードを新しく作る必要があります。その方法を解説します。

createElement

createElementというメソッドがあります。これは、documentが持つメソッドです。つまり、次のように呼び出します。

document.createElement()

これは、HTMLElementを作るメソッドです。次のサンプルを見てみましょう。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="aaaaa">t<strong>es</strong>t</p>

    <script type="text/javascript">
      var newelement = document.createElement('p');
      console.log(newelement);
    </script>
  </body>
</html>
        

変数newelementに、document.createElementの返り値を代入しています。それを表示すると、「HTMLParagraphElement」のように表示されることから、p要素のオブジェクトができていることが分かります。

何の要素ができるかは、引数で指定します。今回は、文字列で「p」と指定しているからp要素ができたのです。何の要素でも作ることができます。

こうしてできたHTMLElementは、document.getElementByIdなどで取得したものと同じように扱うことができます。

ただし、ただできただけで、まだ木構造には加わっていません。そのため、親もありません。そこで、これを木構造に追加する方法をこれから解説します。

ノードを追加する

まず、上のサンプルでのHTML全体の木構造を見てみましょう。

html
|
├――head
|   |
|   └――title
|       |
|       └――#text   "test"
└――body
    |
    ├── p
    |   |
    |   ├――#text   "t"
    |   |
    |   ├――strong
    |   |   |
    |   |   └――#text   "es"
    |   |
    |   └――#text   "t"
    |
    ├――#text
    |
    └――script
        |
        └――#text   "var newel〜;"
        

このようになっています。p要素とscript要素の間に#textがありますが、ここにあるのは改行です。このように、改行があるだけで、テキストノードが発生します(ただし、終了タグの前の改行はテキストノードにならないことになっています)。

今回はbody要素に追加しましょう。ここで、body要素のオブジェクトが必要になります。

body要素にid属性をつけて、getElementByIdで取得することもできますが、body要素の場合はもっとよい方法があります。それは、documentオブジェクトのbodyプロパティです。つまり、 document.bodyですね。これに、そのままbody要素を表すHTMLElementが代入されています。今回はこれを使いましょう。

appendChild

さて、それでは、ノードに子ノードを追加するには、appendChildというメソッドを使います。

このメソッドに引数を渡すと、そのノードの子ノードの一番最後に引数のノードが追加されます。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="aaaaa">t<strong>es</strong>t</p>

    <script type="text/javascript">
      var newelement = document.createElement('p');

      document.body.appendChild(newelement);
    </script>
  </body>
</html>
        

この場合、追加するのは新しく作ったp要素、つまりnewelementに代入されているものです。

これをbody要素の子ノードに追加するので、こうなります。

body
    |
    ├―― p
    |   |
    |   ├――#text
    |   |
    |   ├――strong
    |   |   |
    |   |   └――#text
    |   |
    |   └――#text
    |
    ├――#text
    |
    ├――script
       |
       └――#text
      |
      └―― p

しかし、画面には何の変化もありません。それは、p要素がテキストノードを持っていないからです。p要素の中身が空なのでは、<p></p>を追加したのと同じです。

つまり、追加するp要素に、さらにテキストノードの子ノードを持たせる必要があるわけです。次は、これを解説します。

テキストノードを作成する

テキストノードを持たせるには、当然作る必要があります。テキストノードは、先に紹介したcreateElementでは作れません。別のメソッドを使います。

それは、createTextNodeです。これまた、documentが持つメソッドです。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="aaaaa">t<strong>es</strong>t</p>

    <script type="text/javascript">
      var newtextnode = document.createTextNode("新しいテキストノード");

      console.log(newtextnode.nodeValue);
    </script>
  </body>
</html>
        

引数を1つ持っていて、これは作るテキストノードの中身を指定します。

つまり、「新しいテキストノード」という中身を持つテキストノードを作っています。

できたテキストノードは戻り値として得ることができます。今回は、それをnewtextnodeに代入しています。

できたもののnodeValueプロパティ(二章第三回参照)を見てみるとその中身が表示されることから、これはテキストノードであることが分かります。

さて、これをp要素に追加するのは、さっきと同じappendChildです。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="aaaaa">t<strong>es</strong>t</p>

    <script type="text/javascript">
      var newelement = document.createElement('p');
      var newtextnode = document.createTextNode("新しいテキストノード");

      newelement.appendChild(newtextnode);
    </script>
  </body>
</html>
        

newelementの子ノードにnewtextnodeを追加しています。

また、ここで、newelementは独立した木構造を持っています。実際に画面に表示されている、html要素を頂点とした木構造とは別に、今作ったばっかりのp要素を頂点とした木構造があるのです。

 p

↓↓↓

p
  |
  └――#text   "新しいテキストノード"
        

さて、この木構造を持ったノードを別のノードの親にすると、木構造がまとめてくっつきます。つまり、

body
|
├―― p
|   |
|   ├――#text
|   |
|   ├――strong
|   |   |
|   |   └――#text
|   |
|   └――#text
|
├――#text
|
├――script
   |
   └――#text
  |
  └――  p
        |
        └――#text

        

というようになります。実際にやってみましょう。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="aaaaa">t<strong>es</strong>t</p>

    <script type="text/javascript">
      var newelement = document.createElement('p');
      var newtextnode = document.createTextNode("新しいテキストノード");

      newelement.appendChild(newtextnode);
      document.body.appendChild(newelement);
    </script>
  </body>
</html>
        

newelementをbody要素にappendChildしています。

ここで、画面に「新しいテキストノード」と表示されました。上の図の通りになったのです。

ちなみに、まずp要素を作ってbody要素に追加してから、あとでp要素にテキストノードを追加しても結果は同じになります。

変数newelementに入っているp要素のHTMLElementをbody要素に追加した時点で、変数newelementは「(文書全体の)木構造の一部」としてのp要素を表すようになります。もっとも、指すものはまったく同じです。p要素の立ち位置が少し変わっただけです。

これで、かなり自由に文書を操作できるようになったと思います。もちろん、作った要素に、別の要素を作ってまたくっつけることもできます。