🦙

JavaScript DOM操作の基本

2023/01/15に公開

DOM操作の基本を取得しよう

DOM操作

  • Webサイトを動的に書き換える技術
  • Document Object Model(DOM)という、HTMLやXMLをアプリケーションから操作するための仕組みを利用

DOMツリー

DOMツリーとは
HTMLドキュメントやXMLドキュメントをツリー構造として表現したもの

ノード

ノードとは

  • HTMLに書かれている各要素は、DOMツリーの中ではノードと呼ばれる
  • 文書を構成する要素、属性、テキストといったオブジェクトをノードと呼ぶ
  • 要素ノード
  • 属性ノード
  • テキストノード
    ※DOMツリー1つ1つのオブジェクトがノード

補足:オブジェクトとは?
関連のあるデータと機能の集合

DOMの仕様策定について

  • DOMの仕様は、Level1~4がW3Cにより策定
  • 最新版は、WHATWG(Web Hypertext Application Technology working Group)というコミュニティーがLiving Standardとして定義

living Standardとは標準仕様という意味

ブラウザオブジェクトの階層構造

windowが頂点にあり、
その下にscreen, document, location, navigator,history
documentの下に
Forms,anchors,images
formsの下に
elements

といった階層構造になっている

補足
ブラウザオブジェクト内にあるドキュメントオブジェクトがいわゆるDOMのことを指す

それぞれのオブジェクトについて説明〜

Windowオブジェクト

  • ブラウザを操作するための機能を集めたオブジェクト
  • ブラウザオブジェクトの階層構造の最上位に位置する

Documentオブジェクト

  • Windowオブジェクト内に表示された、HTMLで表現されているコンテンツを保持しているオブジェクト
  • Window内に表示されたドキュメントを操作するのは、Documentオブジェクトの役割

補足
Documentオブジェクトは、いわゆるDOMのことを指します

Locationオブジェクト

  • 現在表示されているページのロケーションに関する情報を提供する
  • 現在の表示URLアドレスに関する情報を取得できる

Historyオブジェクト

  • ブラウザの履歴の操作
  • 画面上に表示しているページの移動などの操作
  • ブラウザ名やバージョンなど、ブラウザ固有の情報を提供する

Screenオブジェクト

  • ディスプレイに関する情報を提供する

Formオブジェクト

  • Formに関する情報を提供する
  • Formの操作ができる

Anchorオブジェクト

  • ページ上のアンカー(<a>)に関する情報を扱う

Imagesオブジェクト

  • 画像に関する情報を提供する
  • 画像を操作する機能を提供する

Elementオブジェクト

  • HTMLドキュメントにおける、要素(タグ)の事
  • 例:<p>JavaScriptの基礎</p>像に関する情報を提供する

IDをキーに要素を取得しよう

getElementByIdメソッド

説明
指定したidを持つ要素を1つ取得する

構文
document.ElementById(id)
id: 取得したい要素のid値

補足
指定したidを持つ要素がなければ、nullを返す
null:オブジェクトが存在しないことを表す

elementは日本語でいうと要素のこと
1つのelementを取得するメソッドなのでelementが単数系になっているところにも注目!

getElementByIdメソッドはdocumentが持つメソッド
言い換えると、documentオブジェクトが持つ機能

例題

  1. 現在のidがresult要素の、コンテンツ(テキスト)を取得
  2. 取得した要素のコンテンツ(テキスト)を、コンソールに出力

まずindex.htmlファイルでpタグを用意して文字列を入れる
idをresultとする
次にボタンを用意する
ボタンを押した時に処理を実行するようにする

<p id="result">pタグの文字列です</p>
<input id="button" type="button" value="Get!">

main.jsファイル
イベント処理
ボタンをクリックした時に何らかの任意の処理を実行できる
(詳細は別のレクチャー)

const e = document.getElementById('button');
e.addEventListener('click', () => {
    // console.log('Clicked!');
    const result = document.getElementById('result');
    console.log(result.innerText)
}, false);

getElementByIdの引数には取得したい要素のidを指定する
innerTextプロパティを使うことによってテキストだけを取得することができる

※HTML要素で指定するidはページ内で重複しないように注意
基本的に最初に合致した要素を返すが、ブラウザの種類やバージョンによって挙動が異なる可能性がある

タグ名をキーに要素を取得しよう

getElementsByTagNameメソッド

説明
指定したタグ名を持つ要素を取得するメソッド

構文
document.getElementsByTagName(tagName)
※tagName:取得したい要素のタグ名

補足
戻り値は、HTMLCollection(配列と似た構造のデータ)

指定したタグ名が存在しない場合は、空のHTMLCollection([])を返す
(nullではない点に注意)

ページ内に同一のタグは複数配置できるため
要素は複数取得できる場合がある!

例題
タグ名がdivの要素を取得し、そのコンテンツ(テキスト)をコンソールに出力する

HTMLファイル

    <div>element1(div)</div>
    <p>element2(p)</p>
    <div>element3(div)</div>
    <span>element4(span)</span>
    <div>element5(div)</div>

    <input id="button" type="button" value="Get!">

φ(・
この5つの要素からdivタグ要素を取得してテキスト部分をコンソールに出力される処理を作る
トリガーとなるボタンをクリックしたら処理を実行するようにする

main.js

Getボタンをクリックした時の処理を記述
タグ名がdivの要素を取得し、そのコンテンツ(テキスト)をコンソールに出力する

const e = document.getElementById('button');
e.addEventListener('click', () => {
    const elements = document.getElementsByTagName('div');
    for(let i = 0; i < elements.length; i++) {
        console.log(elements[i].innerText);
    }
}, false);

φ(・
elementsが複数形であるところに注意
変数elementsにはdivタグの要素が入る
1ページに複数のdivタグを設置できるので、複数の要素を取得できる場合もある
そのため、HTMLCollectionという配列と似た構造のデータが返る
このelementsの中に入っている要素を1件ずつコンソールに出力する処理を記述

for文で配列のindexを変化させながら取得する

for(let i = 0; i < elements.length; i++) {
        console.log(elements[i].innerText);

φ(・
この処理で、for文でelementsの個数分ループ処理を実行して、1件ずつコンソールに出力させることができる

保存して実行

Getボタンをクリックするとdivのものだけを抜き出してそのコンテンツ(divタグ内のテキスト)をコンソールに出力させることができた

Name属性をキーに要素を取得しよう

getElementsByNameメソッド

説明
指定したname属性を持つ要素を取得するメソッド
ラジオボタン、チェックボックスなど、name属性が等しい要素群の取得に利用

構文
document.gertElementsByName(name)
※name:name属性の値

補足
戻り値は、HTMLCollection(配列と似た構造のデータ)
指定したname属性が存在しない場合は、空のHTMLCollection([])を返す
(nullではない点に注意)

例題
テキストボックスとボタンを配置し、ボタンをクリックしたら
Name属性が’result’の要素を取得して、その入力内容(テキスト)をコンソールに出力する

HTMLファイル

    <input name="result" type="text">
    <input id="button" type="button" value="Get!">

main.js

    const elements = document.getElementsByName('result');
    console.log(elements[0].value);

φ(・
getElementsByNameメソッドを使ってname属性がresultの要素を取得して変数に入れる
elementsが複数形であるところに注意
getElementsByNameメソッドはHTMLCollectionという配列が返ってくる
今回は返ってくる値が一つだが、配列は値が複数入るので配列の一番目を取り出したいため
創意上0とする
.valueで文字を取り出している

保存して実行
テキストボックスにテストと入力してGetボタンをクリック
コンソールにテストと表示されればOK

Class属性をキーに要素を取得しよう

getElementsByClassNameメソッド

説明
指定したclass属性を持つ要素を取得するメソッド

構文
document.getElementsByClassName(className)
※className:class属性の値

補足
戻り値は、HTMLCollection(配列と似た構造のデータ)
指定したname属性が存在しない場合は、空のHTMLCollection([])を返す
(nullではない点に注意)

例題
ボタンをクリックすると、class名が’foo’の要素を取得し、そのコンテンツ(テキスト)をコンソールに出力する

HTMLファイル

    <ul>
        <li class="foo">element1</li>
        <li class="bar">element2</li>
        <li class="foo">element3</li>
        <li>element4</li>
        <li class="bar">element5</li>
    </ul>
    <input id="button" type="button" value="Get!">

まずリストを作りクラス名をつける
トリガーとなるボタンを作る

main.jsファイル

const e = document.getElementById('button');
e.addEventListener('click', () => {
    const elements = document.getElementsByClassName('foo');
    for(let i = 0; i < elements.length; i++) {
    console.log(elements[i].innerText);
}
}, false);

φ(・
getElementsByClassNameメソッドを使ってclass属性がfooの要素を取り出してコンソールに出力する処理を記述する
                                                                                                                              
getElementsByClassNameの引数には取得したい要素のclass属性を入れる

これでclass属性fooの要素を変数elementsに入れます
次に変数elementsの中に入っている要素を一件ずつコンソールに出力する処理を記述

for文でelementsの個数分、繰り返し処理を実行して一件ずつコンソールに出力させることができる

保存して実行
element1とelement3が出力されていればOK!

ノードを追加しよう

ノード追加の流れ

  1. 要素/テキストノードを作成
     createElement / createTextNode

  2. ノード同士を組み立て、ドキュメントに追加

createElementメソッド

説明
要素を作成する

構文
document.createElement(elementName)
※ elementName: 要素名

補足
ノードを作成するだけのため、別途ドキュメントに追加する処理が必要

appendChildメソッド

説明
指定された要素を現在の要素の最後の子要素として追加

構文
element.appendChild(node)
※element:要素オブジェクト
※node: 追加する子ノード

戻り値
追加した子ノード

例題

空のリスト、ボタンを配置

ボタンをクリックすると
リストの項目が追加される
追加される文字列は”test”とする

HTMLファイル

    <ul id="list">
    </ul>
    <input id="button" type="button" value="Add!">

まず空のリストを作りidはリストとする
次にボタンを設置する
ブラウザで確認しAdd!ボタンが表示されていればOK!

main.js

const e = document.getElementById('button');
e.addEventListener('click', () => {
const li = document.createElement('li');
const text = document.createTextNode('test');
li.appendChild(text);
const listElement = document.getElementById('list');
listElement.appendChild(li);
}, false);

φ(・
li要素を生成する
次にテキストノードを生成
文字列testをセット
次にliタグの要素にテキストノードテキストを追加
idがリストのulタグにliを追加
具体的にはliタグで囲まれたテストという文字列が追加される
<li>test</li>

ボタンを押すとul要素の子要素に追加されていく
Add!ボタンをクリックすると・testが追加される

Webページをリロードしないのにも関わらず
動的に要素を追加してWebページを書き換えることができた

ノードを置換しよう

replaceChildメソッド

説明
指定した子ノードを置き換える

構文
replaceNode = parentNode.replaceChild(newChild, oldChild)
※parentNode :置き換え対象の親ノード
※newChild :置き換え後のノード
※oldChild :置き換え対象のノード
※replaceNode :置き換えられたノード

補足
newChildと、oldChildを入れ替える。(appendChildと、removeChildを同時に行う)

例題
リストをボタンを配置
ボタンをクリックすると
リストの子要素を置換する処理

HTML

    <ul>
        <li id="oldList">old element</li>
    </ul>
    <input id="button" type="button" value="Replace!">

リストと子要素を作っていく
次にボタンを設置する

main.js

const e = document.getElementById('button');
e.addEventListener('click', () => {
    const newList = document.createElement('li');
    newList.setAttribute('id', 'newList');
    const newText = document.createTextNode('new element');
    newList.appendChild(newText);
    const oldList = document.getElementById('oldList');
    const parentNode = oldList.parentNode;
    parentNode.replaceChild(newList, oldList);
}, false);

φ(・
クリックのイベントハンドラーの処理として空のli要素を作成
生成したノードにid属性newListを付与
テキストノードを生成
生成したノードを空のli要素の子ノードとして追加
置換前の変数oldListの参照を変数oldListに代入
置換前のidがoldListの要素の参照を変数oldListに代入
(参照というのは、ざっくりいうとオブジェクトへのリンクのことをいう)
親ノードulの参照を変数parentNodeに代入
ノードoldListを新規作成したli要素newListと置換

動作確認をする

Elementsタグを開いておく

・old element
と表示されている

Replace!ボタンをクリックすると
ノードの置換が行われる

・new element
になる

この様子はデベロッパーツールのelementタグでも確認できる

ノードを削除しよう

removeChildメソッド

説明
指定した子ノードを取り除く

構文
oldChild = element.removeChild(child)
※child:DOMから取り除くコード
※oldChild:取り除かれた子ノードの参照

補足
取り除いたノードoldChildは、再利用できる

例題
リストとボタンを設置

ボタンをクリックすると、
リストの子要素が最後のものから削除される

HTMLファイル

    <ul id="list">
        <li>element1</li>
        <li>element2</li>
        <li>element3</li>
        <li>element4</li>
        <li>element5</li>
    </ul>
    <input id="button" type="button" value="Remove!">

まずリストを作っていく
liタグのidはListとする

main.js

const e = document.getElementById('button');
e.addEventListener('click', () => {
    const parentElement = document.getElementById('list');
    const elements = parentElement.getElementsByTagName('li');
    const removeIndex = elements.length - 1;
    // console.log(elements.length);
    parentElement.removeChild(elements[removeIndex]);
}, false);

φ(・
idリストの要素を取得する
次にタグがliのものの要素を取得
次に変数elementsに入っている要素から削除するインデックス番号を取得する
配列のインデックスは0から始まるので -1している
elements.lengthは配列の個数を表している
リストの子要素が最後のものから削除する
ここでは、element5を削除したいので5から1を引いて4を削除する要素のインデックスとして指定する

保存して実行
elementsタブを開いておく
liタグの要素が5個あるのが確認できる
Remove!ボタンをクリックすると
・element5が削除される
elementsタブでも一つ削除されて4つになっている
またクリックしていくとすべて削除することができる

演習:DOM操作

「ノードを追加」のレクチャーで学習したコードを、改修
ユーザーがテキストボックスに文字列を入力後、
ユーザーがボタンを押すと
リストの最後の項目として文字列が追加される

補足
テキストボックスの要素を取得するには、getElementByIdメソッドを利用できる

HTMLファイル

    <ul id="list">
    </ul>
    <input id="textBox" type="text">
    <input id="button" type="button" value="Add!">
    <script src="main.js"></script>

テキストボックスを追加

main.js

const e = document.getElementById('button');
e.addEventListener('click', () => {
    const textBox = document.getElementById('textBox');
    const li = document.createElement('li');
    const text = document.createTextNode(textBox.value);
    li.appendChild(text);
    const listElement = document.getElementById('list');
    listElement.appendChild(li); // <li>test</li>
}, false);

テキストボックスの要素を取得

const textBox = document.getElementById('textBox');

次にテキストノードを生成するところを改修

const text = document.createTextNode(textBox.value);

テキストボックスに入力された文字列に変更
ここでのvalueはテキストボックスに格納された値を指している

デベロッパーツールでもエレメントが追加される様子を確認できる


1回だけ聞いて理解できる人はいないって
言われた言葉を思い返して
諦めず繰り返し講座を聞いてる~
世の中結局は続けたもん勝ちだ
小さくても知識を取り込んでいこう
パワー

Discussion