DOMおれおれAdvent Calendar 2015 – 10日目
作り方
各種と言いながら三種類だけだけど。
実例は挿入の方に。
要素ノード
createElement(tagName)
で作ります。
子として作るなら innerHTML
も使えます。
文字列ノード
createTextNode(text)
で作ります。文字列ノードの文字列の内容は後から nodeValue
で取得、設定できます。
子として作るなら textContent
も使えます。
文書断片 (document fragment)
createDocumentFragment()
で作ります。
使い方は後で。
複製して作成
cloneNode()
を使うと、既存のノードを複製して新しいノードを作成する事ができます。
// elLabel = <label class="super-label"><input type="checkbox" checked>同意する</label> var elNewLabel = elLabel.cloneNode(); // elNewLabel = <label class="super-label"></label>
あ、ノードを複製するだけなので、子ノードは空です。子孫もまとめて複製する場合は引数でフラグを与えてやります。
// elLabel = <label class="super-label"><input type="checkbox" checked>同意する</label> var elNewLabel = elLabel.cloneNode(deep); // elNewLabel = <label class="super-label"><input type="checkbox" checked>同意する</label>
たくさんのノードを作るとき何度もDOM操作を繰り返すより、一度作って複製からの微調整、の方が高速かもね。まあそういうのはテンプレートエンジンに任せちゃった方が良いけれど。
あとは破壊的変更をしたいけど途中で(エラーとかで)中止するときとか。複製してからそっちを操作して、最後に差し替え。
挿入
末子として挿入
appendChild(el)
で、自分の子要素の最後に挿入します。
// 親の要素ノードを作る var elLabel = document.createElement('label'); // 要素ノードを作る var elCheckbox = document.createElement('input'); elCheckbox.type = 'checkbox'; elCheckbox.checked = true; // 文字列ノードを作る var tLabel = document.createTextNode('同意する'); // 末子に挿入 elLabel.appendChild(elCheckbox); elLabel.appendChild(tLabel); // elLabel = <label><input type="checkbox" checked>同意する</label>
HTMLをまとめて挿入
innerHTML
を使って、文字列から作成します。上↑と同じ結果になります。
// 親の要素ノードを作る var elLabel = document.createElement('label'); // HTMLをまとめて挿入 elLabel.innerHTML = '<input type="checkbox" checked>同意する'; // elLabel = <label><input type="checkbox" checked>同意する</label>
(本当は checked
のところがちょっと違うけども。)
要素を指定の位置に挿入
appendChild()
だと常に最後に挿入されますが、最後じゃなくて途中に挿入する場合は insertBefore()
を使います。
// 親の要素ノードを作る var elLabel = document.createElement('label'); // 要素ノードを作る var elCheckbox = document.createElement('input'); elCheckbox.type = 'checkbox'; elCheckbox.checked = true; // 文字列ノードを作る var tLabel = document.createTextNode('同意する'); // 先に末子にしたいノードを挿入してみる elLabel.appendChild(tLabel); // elLabel = <label>同意する</label> // さっき挿入した要素の直前に挿入 elLabel.insertBefore(elCheckbox, tLabel); // elLabel = <label><input type="checkbox" checked>同意する</label>
ちなみに insertAfter()
はないです。参照ノードの次のノードが nextSibling
で得られるので、これを使いましょう。
elLabel.insertBefore(elCheckbox, tLabel.nextSibling); // elLabel = <label>同意する<input type="checkbox" checked></label>
参照ノードの次がないとき nextSibling
は null
になりますが、その場合 insertBefore()
は末子に挿入します。 appendChild()
と同じになるという事ですね。やったね。
要素をまとめて挿入
文書断片 (document fragment) を使うとまとめて挿入できます。
// elList = // <ul> // <li>1</li> // <li>2</li> // <li id="reference">5</li> // </ul> // 挿入する要素を用意 var elItem3 = document.createElement('li'); elItem3.textContent = '3 (New!)'; var elItem4 = document.createElement('li'); elItem4.textContent = '4 (New!)'; // 文書断片を用意 var fragment = document.createDocumentFragment(); fragment.appendChild(elItem3); fragment.appendChild(elItem4); // まとめて挿入 var elReference = elList.querySelector('#reference'); elList.insertBefore(fragment, elReference); // elList = // <ul> // <li>1</li> // <li>2</li> // <li>3 (New!)</li> // <li>4 (New!)</li> // <li id="reference">5</li> // </ul>
基本的に挿入系APIは要素や文字列のノードに限らず、文書断片ノードでも使えます。文書断片の場合はそれ自体ではなく、それに格納されているノードが挿入されます。
差し替えて挿入
replaceChild()
で既存の要素を任意の要素に差し替える事ができます。
// el = <div><img src="img1.png" /></div> var elNewImg = document.createElement('img'); img.setAttribute('src', 'img2.png'); el.replaceChild(elNewImg, el.firstChild); // el = <div><img src="img2.png" /></div>
参考
- document.createElement – Web API インターフェイス | MDN
- document.createTextNode – Web API インターフェイス | MDN
- Document.createDocumentFragment() – Web APIs | MDN
- DocumentFragment – Web API インターフェイス | MDN
- Node.cloneNode – Web API インターフェイス | MDN
- Node.appendChild – Web API インターフェイス | MDN
- Node.insertBefore – Web API インターフェイス | MDN
- Node.nextSibling – Web APIs | MDN
- Node.replaceChild – Web API インターフェイス | MDN