JavaScript で TextNode を操作する
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ 色々操作できた
◆ 覚えておいて役立つのは data プロパティ と splitText と normalize メソッド
◆ 覚えておいて役立つのは data プロパティ と splitText と normalize メソッド
HTML を扱うときはあまり TextNode を意識することはないですが XML パースしてテキスト部分も使った処理するときや JavaScript で扱いやすいように span などのタグがつけられずに
getElementXXX 系は名前の通り Element つまり div タグなどのタグに対応した要素を取得します
TextNode がほしいときには便利な検索はできません
何番目の子要素 という指定になります
Element だけなら
他にも
Element が欲しいなら
になります
Element 以外の Node を取得する方法だと TextNode 以外のノードもとれます
CDATASection とか Comment などがあります
ノードの種類には document や doctype や document fragment もありますが子要素になってることはないので基本上に書いたものだけです
一応 Element の属性 id とか class とかもノードだったりします
new Text と書くと楽ですが HTML の Element のように
ただ append するなら
のどれかのプロパティにアクセスすればおっけいです
どれでもいいですが wholeText は読み取り専用で書き換えてもテキストに変更はありません
それ以外のプロパティは変更すると テキストが書き換わります
例えばこんな DOM があって
JavaScript で時間みて動的に書き換えよう
……なぜか span で変更したいところが囲まれていない!!
そんなときでも
ところで Text の継承はこうなっています
Node から先は HTML の Element も一緒です
div だとこうなってます
さっきあった 4 つのプロパティですが
Text 自体のプロパティは wholeText だけです
data は CharacterData のプロパティです
textContent と nodeValue は Node のプロパティです
HTML の Element でも textContent は使えますよね
nodeValue の方は HTML の Element では null になっています
使うサンプルはさっきの
data を += しても一緒です
ポジションとテキストを引数にします
ポジションと文字数とテキストを指定します
指定された範囲の文字がテキストに置き換わります
文字数が 0 なら追加されるだけで insertData と一緒です
テキストが空文字なら指定範囲の文字が削除されるだけになります
replaceData のテキストがないだけです
空文字指定したようなものです
覚えるよりは テキストを普通に string 型で作って data に上書きでいいと思います
昔の DOM 操作の名残感がすごくあります
返り値が分割後のノードです
分割するわけですから元になるノードへの参照は持っているので分割された後ろ側のノードの参照が受け取れます
長いテキストで一部だけ書き換えたいときに 全部書き換えるのは面倒ですから 書き換えたいところだけ切り離しておくのはアリだと思います
子要素の なので親要素のメソッドです
分割するノードは 0 文字にもできます
全部くっつけるしかできないので部分的にまとめたいなら手動でやるしかないかも
<div>
ここを書き換える
<div>あ</div>
<div>aaa<p>bbb</p>dここも書き換えるd</div>
<div>ccc</div>
</div>
こういう中途半端なところを書き換えたいときには TextNode を操作することになりますここを書き換える
<div>あ</div>
<div>aaa<p>bbb</p>dここも書き換えるd</div>
<div>ccc</div>
</div>
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
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
--> CharacterData
--> Node
--> EventTarget
--> Object
Node から先は HTML の Element も一緒です
div だとこうなってます
HTMLDivElement
--> HTMLElement
--> Element
--> Node
-->
--> 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)
console.log(div.textContent)
今日は日曜日かも
data を += しても一緒です
div.childNodes[1].data += "かも"
insertData
appendData では最後でしたが好きなところに追加できますポジションとテキストを引数にします
div.childNodes[1].insertData(0, "たぶん")
console.log(div.textContent)
console.log(div.textContent)
今日はたぶん日曜日
div.childNodes[1].insertData(2, "の次の")
console.log(div.textContent)
console.log(div.textContent)
今日は日曜の次の日
replaceData
文字を置き換えますポジションと文字数とテキストを指定します
指定された範囲の文字がテキストに置き換わります
div.childNodes[1].replaceData(0, 1, "水")
console.log(div.textContent)
console.log(div.textContent)
今日は水曜日
文字数が 0 なら追加されるだけで insertData と一緒です
テキストが空文字なら指定範囲の文字が削除されるだけになります
deleteData
指定の範囲の文字を削除しますreplaceData のテキストがないだけです
空文字指定したようなものです
div.childNodes[1].deleteData(2, 1)
console.log(div.textContent)
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)
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)
t.splitText(3)
console.log(div.childNodes.length)
div.normalize()
console.log(div.childNodes.length)
4
2
2
分割するノードは 0 文字にもできます
全部くっつけるしかできないので部分的にまとめたいなら手動でやるしかないかも
textnode // Text
var next = textnode.nextSibling
textnode.data += next.data
next.remove()
var next = textnode.nextSibling
textnode.data += next.data
next.remove()