JavaScript で HTML (DOM) を操作

JavaScript での HTML (DOM) 操作について。

標準は, 2003年1月の DOM Level 2 HTML だったが, WHATWG Living Standard で置き換えられた。

さらには, React の仮想DOM (Virtual DOM; VDOM) があれば、直接 DOM を操作する機会はほとんどなさそう。

(2002.12.14)

HTML table 要素は,JavaScriptでは HTMLTableElement オブジェクトとなる。HTMLTableElement#rows プロパティは,行オブジェクトの集合である HTMLCollection オブジェクトを返す。このオブジェクトのitem()メソッドで行オブジェクトを取り出せる。行は HTMLTableRowElement オブジェクトとなる。

対象DOM クラス
HTMLTableElement
キャプション HTMLTableCaptionElement
行グループ: thead, tfoot, tbody HTMLTableSectionElement
列グループ: colgroup, col HTMLTableColElement
行: tr HTMLTableRowElement
セル: th, td HTMLTableCellElement

値を得る

特定のセルの値を取り出すには,次のようにする。

<table id="hoge">
  <tr><td>cell 1<td>cell 2
</table>
function cell(id, x, y) {
  table = document.getElementById(id);
  row = table.rows.item(y);
  cell = row.cells.item(x);
  document.write("cell(" + x + ", " + y + ") is " + cell.firstChild.data);
}
cell('hoge', 1, 0);

行を追加する

利用者に何らかのデータを表形式で入力してもらうとき,最初に生成したフォームの表の行数では足りなくなることがある。余裕を持ってフォームを生成すればいいが,あまりにも行数が多いと結構間抜け。そこで,JavaScriptで行を追加する。

HTMLTableElement#insertRow() メソッドで行を追加し,HTMLTableRowElement#insertCell()メソッドでセルを追加する。

<table id="foo" border="1">
  <tr><td>1<td>2<td>3
  <tr><td>4<td>5<td>6
  <tr><td>7<td>8<td>9
</table>
function add_row(id) {
  table = document.getElementById(id);
  new_row = table.insertRow(table.rows.length);
  new_row.insertCell(0).appendChild(document.createTextNode('foo'));
  new_row.insertCell(1).appendChild(document.createTextNode('bar'));
  new_row.insertCell(2).appendChild(document.createTextNode('baz'));
}
add_row('foo');

HTMLTableCellElementクラス

(2002.4.28) この節を追加。

th, td要素を表すクラス。

プロパティ

firstChild
最初の子要素オブジェクトを返す。例えばTextオブジェクト。

メソッド

removeChild(node)
子要素を取り除く。
appendChild(node)
子要素を追加する。

メッセージボックス

(2002.12.2)

windowオブジェクトのalertメソッドを使う。

function a() {
  window.alert('メッセージボックス');
}

次のようにして呼び出す。

<button onclick="a()">メッセージボックス</button>

ツリー

(2002.12.2)

要素オブジェクトのstyleプロパティのdisplayプロパティを使う。このプロパティは,CSSのdisplayプロパティと対応しており,'block'や'none'を設定できる。

また,img要素オブジェクトのsrcプロパティを変更して,例えばフォルダアイコンを表示したりする。

function tree_toggle(id) {
  e = document.getElementById(id);
  i = document.getElementById(id + 'i');
  if (e.style.display == "none") {
    e.style.display = "block";
    i.src = "../images/tree_o.gif";
  }
  else {
    e.style.display = "none";
    i.src = "../images/tree_c.gif";
  }
}

初期状態は,次のように設定する。

aタグのhref属性でtree_toggle()を呼び出すようにする。tree_toggle()の引数として,クリックしたときに折り畳む要素のid属性値を指定する。初期状態で畳むときは,style属性として"display:none"を設定する。

人間がいちいちやっていると大変なので,サーバ側で自動的に生成するのが吉。

<img src="../images/tree_o.gif" id="t1i"> 
<a href="javascript:tree_toggle('t1')">parent</a>
<div id="t1" >
  <img src="../images/tree_c.gif" id="t2i"> 
  <a href="javascript:tree_toggle('t2')">child</a>
  <div id="t2" style="display:none">
    sub text
  </div>
</div>

フォーム

HTMLInputElementクラス

(2002.4.28) この節を追加。

HTML input要素を表すクラス。

プロパティ

value
コントロール値(文字列)。代入可。

Textクラス

2002.4.28 この節を追加。
2002.12.15 更新

要素の内容としてのテキストを表すクラス。

プロパティ

data
文字列。代入可。
length
長さ。読み取り専用。

Textオブジェクトを生成するには,Document#createTextNode()を使う。

グローバルオブジェクト

ウィンドウ、文書、それからWebブラウザ自身を表すオブジェクト。

それぞれのWebブラウザで, 次のようなスクリプトを実行した。

<script>
function prop_out(obj) {
  document.write("<p>", obj, "<br>\n");
  for (prop in obj) {
    document.write(prop, " ");
  }
}
prop_out(window);
prop_out(navigator);
prop_out(document);
prop_out(history);
prop_out(location); // "[...]"ではなく,値が返る。
prop_out(document.forms);
prop_out(document.anchors);
prop_out(window.screen);
</script>

1. windowオブジェクト

[2020.11] 現代では, WHATWG HTML Living Standard にて標準化されている。

closed defaultStatus document frames history length location name navigator opener parent screen self status top window

window.opener

[2020.11] noopener について。

window.opener 属性は, 新しく開かれたウィンドウから, 元のウィンドウを得る。例えば, 新しい方のウィンドウで window.opener.close() すると、元のウィンドウを閉じることができる。

現在のウィンドウが別のウィンドウから開かれたものでない場合, null を返す. セキュリティ上のリスクがあるため, same-origin でない場合は, オブジェクトは得られるが, 機能が制限される。

JavaScript で開いた場合だけでなく, a HTML要素でも, target 属性をつければ新しいウィンドウを開ける。

<a href="http://example.com/new_window.html" target="_blank">Click here!</a>

機能が制限されると云っても, 元ウィンドウのアドレスをこっそり移動させて phishing 攻撃することが可能。次の図で, new_window.html が元のウィンドウを書き換える。ユーザは元のウィンドウと思って, evil.html で何かをする。


出典 https://yoru9zine.hatenablog.com/entry/2017/03/17/230729

そこで, Firefox 79 から, a target="_blank" で開かれたウィンドウは, rel="noopener" が付いているとみなされる。新しいウィンドウから元のウィンドウオブジェクトを取得できなくなる。逆に, 新しいウィンドウから操作してほしいときは, 明示的に rel="opener" を付けなければならない。

Chrome 88 から同様の挙動に追従。

2. navigator オブジェクト

グローバルな navigatorオブジェクトか, window.navigator オブジェクト。どちらも同じ。Webブラウザの情報を持つ。

appCodeName appName appVersion cookieEnabled mimeTypes platform plugins userAgent

3. document オブジェクト

これも, グローバルなオブジェクトか, window.document オブジェクト。どちらも同じ。表示されている文書。

HTML であれば HTMLDocument クラス. Document クラスから派生している。

URL alinkColor anchors applets bgColor body childNodes cookie dir documentElement domain embeds fgColor forms images lastModified linkColor links location plugins referrer styleSheets title vlinkColor

プロパティ:

title
ページのタイトル。文字列であり,代入もできる。
fgColor deprecated
文字色。"#ffffff"という形式の文字列。この形式の文字列を代入すると,色が変わる。HTML body 要素を使え。
bgColor deprecated
背景色。"#ffffff"という形式の文字列。この形式の文字列を代入すると,色が変わる。HTML body 要素を使え。

メソッド:

all(id_str)
id_str を持つ要素オブジェクトを返す。IE専用。
getElementById(id_str) Document で宣言。
要素オブジェクトを返す。HTMLTableCellElement オブジェクト,HTMLInputElement オブジェクトなど, Element 派生オブジェクトを返す。見つからないときは null.
getElementsByName(elementName)
NodeList を返す。
createTextNode(str)
Text オブジェクトを生成して返す。

GlobalEventHandlers インタフェイス

すべてのHTML要素, document オブジェクトおよび window オブジェクトでサポートされるイベントハンドラ。

onSelectStart, onSelectionChange はいまだに草案。

Selection API W3C Working Draft 18 August 2020. Internet Explorer や Chrome でも昔から使えていた。W3C の最初の草案は2014年10月。2020年になってもまだ草案。短い仕様に, 何がそんなに時間が掛かるのか。

外部リンク