◆ 色々操作できた
◆ 覚えておいて役立つのは data プロパティ と splitText と normalize メソッド

HTML を扱うときはあまり TextNode を意識することはないですが XML パースしてテキスト部分も使った処理するときや JavaScript で扱いやすいように span などのタグがつけられずに
<div>
    ここを書き換える
    <div>あ</div>
    <div>aaa<p>bbb</p>dここも書き換えるd</div>
    <div>ccc</div>
</div>
こういう中途半端なところを書き換えたいときには TextNode を操作することになります

TextNode を取得する

TextNode を取得するには XPATH が便利ですがブラウザでは 1.0 しか対応してないですし devtools の $x なしだと扱いづらいので使わないことにします


getElementXXX 系は名前の通り Element つまり div タグなどのタグに対応した要素を取得します
TextNode がほしいときには便利な検索はできません
何番目の子要素 という指定になります
document.body.childNodes
で body のすべての子ノードが取得できます
Element だけなら
document.body.children
です

他にも
document.body.firstChild
は TextNode なども含めた最初のノードを取得します

Element が欲しいなら
document.body.firstElementChild

になります

Element 以外の Node を取得する方法だと TextNode 以外のノードもとれます
CDATASection とか Comment などがあります

ノードの種類には document や doctype や document fragment もありますが子要素になってることはないので基本上に書いたものだけです
一応 Element の属性 id とか class とかもノードだったりします

Text 型

TextNode は JavaScript では Text という型になっています
dir(new Text("abcd"))
#text
    baseURI: "http://var.blog.jp/t/blogmd/blogmd3.html"
    childNodes: NodeList[0]
    data: "abcd"
    firstChild: null
    isConnected: false
    (略)
    __proto__: Text

new Text と書くと楽ですが HTML の Element のように
document.createTextNode("abcd")
とも書けます

ただ append するなら
document.body.append("てきすと")
とするだけでもいいので あまりインスタンス作成はしないかもです

Text のプロパティ

TextNode のテキストが欲しい時には

  • data
  • wholeText
  • textContent
  • nodeValue

のどれかのプロパティにアクセスすればおっけいです

どれでもいいですが wholeText は読み取り専用で書き換えてもテキストに変更はありません

それ以外のプロパティは変更すると テキストが書き換わります

例えばこんな DOM があって
<div id="div"><span class="small">今日は</span>日曜日</div>
日曜日のところをリアルタイムに変更したい
JavaScript で時間みて動的に書き換えよう
……なぜか span で変更したいところが囲まれていない!!

そんなときでも
document.getElementById("div").childNodes[1].data = "月曜日"
こうすれば 「今日は月曜日」 に書き換えることができます


ところで Text の継承はこうなっています
Text
--> CharacterData
    --> Node
        --> EventTarget
            --> Object

Node から先は HTML の Element も一緒です
div だとこうなってます
HTMLDivElement
--> HTMLElement
    --> Element
        --> Node
            -->

さっきあった 4 つのプロパティですが

Text 自体のプロパティは wholeText だけです

data は CharacterData のプロパティです

textContent と nodeValue は Node のプロパティです
HTML の Element でも textContent は使えますよね
nodeValue の方は HTML の Element では null になっています

テキスト操作系メソッド

data プロパティを書き換えてしまえばいいのですが テキスト部分を操作するメソッドがいくつかあります

使うサンプルはさっきの
<div id="div"><span class="small">今日は</span>日曜日</div>
にします

appendData

最後に追加します
div.childNodes[1].appendData("かも")
console.log(div.textContent)
今日は日曜日かも

data を += しても一緒です
div.childNodes[1].data += "かも"

insertData

appendData では最後でしたが好きなところに追加できます
ポジションとテキストを引数にします
div.childNodes[1].insertData(0, "たぶん")
console.log(div.textContent)
今日はたぶん日曜日
div.childNodes[1].insertData(2, "の次の")
console.log(div.textContent)
今日は日曜の次の日

replaceData

文字を置き換えます
ポジションと文字数とテキストを指定します
指定された範囲の文字がテキストに置き換わります
div.childNodes[1].replaceData(0, 1, "水")
console.log(div.textContent)
今日は水曜日

文字数が 0 なら追加されるだけで insertData と一緒です
テキストが空文字なら指定範囲の文字が削除されるだけになります

deleteData

指定の範囲の文字を削除します
replaceData のテキストがないだけです
空文字指定したようなものです
div.childNodes[1].deleteData(2, 1)
console.log(div.textContent)
今日は日曜




覚えるよりは テキストを普通に string 型で作って data に上書きでいいと思います
昔の DOM 操作の名残感がすごくあります

分割結合

ここからは使えるかもしれないメソッドです

splitText

TextNode を分割できます
var next = div.childNodes[1].splitText(2)
console.log(div.childNodes[1].data)
console.log(next.data)
日曜

返り値が分割後のノードです
分割するわけですから元になるノードへの参照は持っているので分割された後ろ側のノードの参照が受け取れます

長いテキストで一部だけ書き換えたいときに 全部書き換えるのは面倒ですから 書き換えたいところだけ切り離しておくのはアリだと思います

normalize

子要素の連続する TextNode を結合します
子要素の なので親要素のメソッドです
var t = div.childNodes[1].splitText(0)
t.splitText(3)
console.log(div.childNodes.length)
div.normalize()
console.log(div.childNodes.length)
4
2

分割するノードは 0 文字にもできます
全部くっつけるしかできないので部分的にまとめたいなら手動でやるしかないかも
textnode // Text
var next = textnode.nextSibling
textnode.data += next.data
next.remove()

まとめ

めったに使わない TextNode だけど色々できました