1. はじめに
ウェブページはHTMLで構造が定義され、CSSで装飾されます。しかし、ユーザーの操作に応じて内容を変化させたり、アニメーションを加えたりといった動的な動きを実現するためには、JavaScriptが必要です。JavaScriptは、HTMLで記述されたウェブページの構造(DOM)を操作し、ユーザーの様々な行動(イベント)に反応することで、インタラクティブな体験を提供します。
このページでは、JavaScriptを使ってウェブページを動的に操るための基本である「DOM操作」と「イベントハンドリング」について、具体的なコード例を交えながら解説します。
2. DOM操作の基本
2.1. DOM(Document Object Model)とは?
DOMは、HTMLやXML文書のプログラミングインターフェースです。簡単に言うと、ウェブページ上のすべての要素(段落、見出し、画像、ボタンなど)をJavaScriptから操作できるように、オブジェクトのツリー構造として表現したものです。JavaScriptはこのDOMを通して、要素の追加、削除、変更などを行います。
HTMLコード:
こんにちは
これはテキストです。
は、DOMでは以下のようなツリー構造として表現されます。
- Document
- HTML
- HEAD
- BODY
- DIV (id="container")
- H1
- P (class="text")
- DIV (id="container")
- HTML
2.2. 要素の取得
DOMを操作する最初の一歩は、操作したいHTML要素をJavaScriptから「取得」することです。
代表的な要素取得メソッド:
document.getElementById('id名'): 指定されたIDを持つ要素を一つ取得します。document.getElementsByClassName('クラス名'): 指定されたクラス名を持つ要素をすべて取得します(HTMLCollectionとして)。document.getElementsByTagName('タグ名'): 指定されたタグ名を持つ要素をすべて取得します(HTMLCollectionとして)。document.querySelector('CSSセレクタ'): 指定されたCSSセレクタに一致する最初の要素を一つ取得します。document.querySelectorAll('CSSセレクタ'): 指定されたCSSセレクタに一致するすべての要素を取得します(NodeListとして)。
例:
// IDが "myButton" の要素を取得
const myButton = document.getElementById('myButton');
// クラスが "item" のすべての要素を取得
const items = document.getElementsByClassName('item');
// CSSセレクタで最初の段落を取得
const firstParagraph = document.querySelector('p');
// CSSセレクタで全てのリストアイテムを取得
const allListItems = document.querySelectorAll('ul li');
2.3. 要素の作成・追加・削除
既存の要素を操作するだけでなく、新しい要素を作成してページに追加したり、不要な要素を削除したりすることもできます。
document.createElement('タグ名'): 新しいHTML要素を作成します。親要素.appendChild(子要素): 指定した子要素を親要素の最後の子として追加します。親要素.removeChild(子要素): 指定した子要素を親要素から削除します。
例:
// 新しい段落要素を作成
const newParagraph = document.createElement('p');
newParagraph.textContent = '新しく追加されたテキストです!';
// IDが "container" の要素を取得
const container = document.getElementById('container');
// containerの子要素として新しい段落を追加
container.appendChild(newParagraph);
// 追加した段落を削除
// container.removeChild(newParagraph);
2.4. 要素の内容・属性・スタイルの変更
取得した要素のテキスト内容、HTML内容、属性、そしてスタイルをJavaScriptから変更することができます。
要素.textContent: 要素のテキスト内容(タグを含まない)を取得または設定します。要素.innerHTML: 要素のHTML内容(タグを含む)を取得または設定します。要素.setAttribute('属性名', '値'): 要素の属性を設定します。要素.getAttribute('属性名'): 要素の属性の値を取得します。要素.removeAttribute('属性名'): 要素の属性を削除します。要素.style.プロパティ名: 要素のインラインスタイルを変更します(例:要素.style.color = 'red';)。要素.classList.add('クラス名'): 要素にCSSクラスを追加します。要素.classList.remove('クラス名'): 要素からCSSクラスを削除します。要素.classList.toggle('クラス名'): 要素にクラスがあれば削除し、なければ追加します。
例:
const heading = document.getElementById('myHeading');
const image = document.getElementById('myImage');
// テキスト内容を変更
heading.textContent = '新しいタイトル!';
// HTML内容を変更(HTMLタグも認識される)
// heading.innerHTML = '新しいタイトル!';
// 画像のsrc属性とalt属性を変更
image.setAttribute('src', 'images/new-image.jpg');
image.setAttribute('alt', '新しい画像');
// スタイルを直接変更
heading.style.color = 'blue';
heading.style.fontSize = '24px';
// クラスリストを操作
heading.classList.add('highlight'); // highlightクラスを追加
// heading.classList.remove('highlight'); // highlightクラスを削除
// heading.classList.toggle('active'); // activeクラスをトグル
3. イベントハンドリングの基本
3.1. イベントとは?
イベントとは、ウェブページ上で発生する様々な出来事のことです。例えば、ユーザーがボタンをクリックする、マウスカーソルが要素の上を通過する、キーボードのキーを押す、ページが読み込まれる、フォームが送信される、など多岐にわたります。
JavaScriptでは、これらのイベントが発生した際に、特定の処理を実行するように設定することができます。これを「イベントハンドリング」と呼びます。
3.2. イベントリスナーの追加
要素にイベントが発生したときに実行される関数(イベントハンドラ)を設定するには、addEventListener()メソッドを使用するのが一般的です。
要素.addEventListener('イベント名', 関数);
例:
const myButton = document.getElementById('myButton');
// クリックイベントが発生したら、指定された関数を実行
myButton.addEventListener('click', function() {
alert('ボタンがクリックされました!');
});
// アロー関数を使った例
myButton.addEventListener('mouseover', () => {
console.log('マウスがボタンの上に乗りました!');
});
3.3. よく使われるイベントの種類
click: 要素がクリックされた時mouseover: マウスカーソルが要素の上に乗った時mouseout: マウスカーソルが要素から離れた時keydown: キーボードのキーが押された時keyup: キーボードのキーが離された時change: フォーム要素(入力フィールド、セレクトボックスなど)の値が変更された時submit: フォームが送信された時load: ページ全体、または画像などのリソースが完全に読み込まれた時(windowオブジェクトによく使われます)DOMContentLoaded: HTMLドキュメントが完全に読み込まれ、解析された時(画像などのリソースの読み込みは含まない)。JavaScriptのコード実行はこのイベントの後に行うのが一般的です。
3.4. イベントオブジェクト
イベントリスナーに渡される関数は、通常、イベントに関する情報を持つ「イベントオブジェクト」を引数として受け取ります。このオブジェクトには、発生したイベントの種類、ターゲット要素、マウスの座標、押されたキーなどの情報が含まれています。
event.target: イベントが発生した要素(最も内側の要素)event.currentTarget: イベントリスナーがアタッチされている要素event.preventDefault(): イベントのデフォルトの動作(例: リンククリックでのページ遷移、フォーム送信)をキャンセルします。event.stopPropagation(): イベントの伝播(バブリング)を停止します。
例:
const myLink = document.getElementById('myLink');
myLink.addEventListener('click', (event) => {
event.preventDefault(); // デフォルトのリンク遷移を阻止
alert('リンクがクリックされましたが、ページ遷移はしません!');
console.log('クリックされた要素:', event.target);
});
const myInput = document.getElementById('myInput');
myInput.addEventListener('keydown', (event) => {
console.log('押されたキー:', event.key);
console.log('キーコード:', event.keyCode); // 非推奨だがまだ使われる
});
4. 実践例
これまでに学んだDOM操作とイベントハンドリングを組み合わせて、いくつかの実践的な例を見てみましょう。
4.1. ボタンクリックでテキストを変更
「テキスト変更」ボタンをクリックすると、下のテキストが切り替わります。
ここにあるテキストが変化します。
ここにあるテキストが変化します。
// JavaScript (script.js)
document.addEventListener('DOMContentLoaded', () => {
const changeTextButton = document.getElementById('changeTextButton');
const changeTextParagraph = document.getElementById('changeTextParagraph');
let toggle = true;
changeTextButton.addEventListener('click', () => {
if (toggle) {
changeTextParagraph.textContent = 'テキストが変更されました!';
} else {
changeTextParagraph.textContent = '元のテキストに戻りました。';
}
toggle = !toggle; // true/falseを切り替え
});
});
4.2. 画像の表示/非表示をトグル
「画像表示/非表示」ボタンをクリックすると、画像が現れたり消えたりします。
.hidden {
display: none;
}
// JavaScript (script.js)
document.addEventListener('DOMContentLoaded', () => {
const toggleImageButton = document.getElementById('toggleImageButton');
const toggleImage = document.getElementById('toggleImage');
toggleImageButton.addEventListener('click', () => {
toggleImage.classList.toggle('hidden'); // hiddenクラスをトグル
});
});
4.3. フォーム入力内容をリアルタイムで表示
下の入力フィールドに何か入力してみてください。入力内容がリアルタイムで下に表示されます。
入力内容:
入力内容:
// JavaScript (script.js)
document.addEventListener('DOMContentLoaded', () => {
const liveInput = document.getElementById('liveInput');
const displayInput = document.getElementById('displayInput');
// 'input'イベントは入力内容が変更されるたびに発生
liveInput.addEventListener('input', () => {
displayInput.textContent = liveInput.value;
});
});
5. TODOリストの追加と削除
ここでは、JavaScriptを使ったDOM要素の動的な追加と削除を体験してみましょう。下の入力欄に新しいTODOアイテムを入力し、「追加」ボタンをクリックしてみてください。リストにアイテムが追加され、各アイテムの右側にある「削除」ボタンでそのアイテムを消すことができます。
// JavaScript (script.js)
document.addEventListener('DOMContentLoaded', () => {
const todoInput = document.getElementById('todoInput');
const addTodoButton = document.getElementById('addTodoButton');
const todoList = document.getElementById('todoList');
if (addTodoButton && todoInput && todoList) {
addTodoButton.addEventListener('click', () => {
const todoText = todoInput.value.trim(); // 前後の空白を除去
if (todoText !== '') { // 空文字列でなければ追加
// 1. 新しい 要素を作成
const listItem = document.createElement('li');
listItem.classList.add('todo-item'); // スタイリング用にクラスを追加
// 2. テキストと削除ボタンを含む span を作成
const todoTextSpan = document.createElement('span');
todoTextSpan.textContent = todoText;
const deleteButton = document.createElement('button');
deleteButton.textContent = '削除';
deleteButton.classList.add('delete-button'); // スタイリング用にクラスを追加
// 削除ボタンにクリックイベントリスナーを追加
deleteButton.addEventListener('click', () => {
// 親要素 (li) をリスト (ul) から削除
todoList.removeChild(listItem);
});
// 3. li の中にテキストとボタンを追加
listItem.appendChild(todoTextSpan);
listItem.appendChild(deleteButton);
// 4. ul リストに li を追加
todoList.appendChild(listItem);
// 5. 入力フィールドをクリア
todoInput.value = '';
} else {
alert('TODOアイテムを入力してください!');
}
});
// (オプション) Enterキーで追加できるようにする
todoInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
addTodoButton.click(); // ボタンクリックイベントをトリガー
}
});
}
});
6. モーダルウィンドウ(ポップアップ)
このボタンをクリックすると、画面中央にモーダルウィンドウが表示されます。モーダルは、重要な情報をユーザーに提示したり、簡単な入力を促したりする際に使われる一般的なUIパターンです。
「閉じる」ボタン、またはモーダルウィンドウの外側の暗い部分をクリックするとモーダルが閉じます。
// JavaScript (script.js)
document.addEventListener('DOMContentLoaded', () => {
// ... 既存のコード ...
// モーダル関連の要素を取得
const openModalButton = document.getElementById('openModalButton');
const myModal = document.getElementById('myModal');
const closeButton = document.querySelector('.close-button'); // クラス名で取得
// モーダルを開く
if (openModalButton && myModal) {
openModalButton.addEventListener('click', () => {
myModal.style.display = 'block'; // モーダルを表示
myModal.classList.add('fade-in'); // フェードインアニメーション
});
}
// モーダルを閉じる(閉じるボタン)
if (closeButton && myModal) {
closeButton.addEventListener('click', () => {
myModal.classList.remove('fade-in'); // アニメーションクラスを削除
// アニメーション完了後に非表示にするため、少し遅延させる
setTimeout(() => {
myModal.style.display = 'none';
}, 300); // CSSのtransition時間と合わせる
});
}
// モーダルを閉じる(背景クリック)
if (myModal) {
myModal.addEventListener('click', (event) => {
// クリックされたのがモーダル自身(オーバーレイ部分)であれば閉じる
// モーダルコンテンツ内がクリックされた場合は閉じないようにする(伝播防止)
if (event.target === myModal) {
myModal.classList.remove('fade-in');
setTimeout(() => {
myModal.style.display = 'none';
}, 300);
}
});
}
// (オプション) Escキーでモーダルを閉じる
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && myModal.style.display === 'block') {
myModal.classList.remove('fade-in');
setTimeout(() => {
myModal.style.display = 'none';
}, 300);
}
});
});