このシリーズのはじめに「HTML 要素は、ドキュメント オブジェクト モデルを構成するノードです」と書かれています。 要素ノードの種類については、すでに説明しました。このセクションでは、これらのノードへのクエリを可能にする要素 API について説明します。
DOM と AOM
DOM は、ドキュメントにアクセスして操作するための API です。DOM はドキュメント内のすべてのノードのツリーです。子を持つノードもあれば、子を持たないノードもある。ツリーには、要素とその属性、テキストノードが含まれます。
ブラウザツールには上記のようなツリーの可視化機能がありませんが、要素インスペクタでノードを確認できます。
ブラウザのデベロッパー ツールで調べることができるツリー表現は、ユーザー補助ツリーです。AOM は DOM をベースにしています。同様に、ユーザー補助ツリーには、すべてのマークアップ要素、属性、テキストノードを表すオブジェクトが含まれます。
HTML Element API
DOM の中央の文字は「オブジェクト」です。オブジェクト指向プログラミング クラスの入門編で紹介した person
や car
オブジェクトの例と同様に、ドキュメント ツリー内のすべてのノードは JavaScript で操作できるオブジェクトです。
ブラウザには多数の API が用意されており、ネイティブにサポートされているメソッド、イベント、プロパティのクエリと更新が可能です。要素ノードには、要素に設定されたすべての属性に関する情報が含まれます。HTML インターフェースを使用して、要素の属性に関する情報にアクセスできます。たとえば、HTMLImageElement.alt
を使用して、すべての画像の alt
属性を取得できます。
let allImages = document.querySelectorAll('img');
allImages.forEach((imageInstance) => {
console.log(imageInstance.alt);
});
HTML インターフェースが提供するのは、要素の属性にアクセスするだけではなく、より多くの情報にアクセスできます。読み取り専用の HTMLElement.offsetHeight
を使用すると、レイアウトに対する相対的なページ内の各セクションの高さを取得できます。
let allSections = document.querySelectorAll('section');
allSections.forEach((sectionInstance) => {
console.log(sectionInstance.offsetHeight);
});
ユーザーがデバイスの向きやビューポートの幅を変更すると、各 <section>
の高さが変化し、それに応じて DOM プロパティが自動的に更新されます。
HTML インターフェース API は、属性値へのアクセスに限定されません。DOM は、UI の現在の状態に関する分析情報を提供します。HTML API は、この情報のすべてにアクセスできます。動画の長さ、ビューが現在の再生に含まれる場所、動画(または音声)の再生が終了したかどうかをそれぞれ HTMLMediaElement.duration
、HTMLMediaElement.currentTime
、HTMLMediaElement.ended
で確認できます。
使用可能な要素インターフェース
一部のセクション要素を除き、このシリーズでこれまで説明してきた、まだ取り上げていない HTML 要素のほとんどには、DOM インターフェースが関連付けられています。すべての要素の基本インターフェースは Element と適切に命名されています。HTMLElement
は要素から継承され、HTML 要素固有のインターフェースはすべて要素から継承されます。一部の要素固有のインターフェースは、複数の類似した要素によって実装されます。
インターフェースには次のものがあります。
HTMLAnchorElement
-<a>
HTMLAreaElement
-<area>
HTMLAudioElement
-<audio>
HTMLBaseElement
-<base>
HTMLButtonElement
-<button>
HTMLCanvasElement
-<canvas>
HTMLDataElement
-<data>
HTMLDataListElement
-<datalist>
HTMLDetailsElement
-<details>
HTMLDialogElement
-<dialog>
HTMLEmbedElement
-<embed>
HTMLFieldSetElement
-<fieldset>
HTMLFormElement
-<form>
HTMLHtmlElement
-<html>
HTMLIFrameElement
-<iframe>
HTMLImageElement
-<img>
HTMLInputElement
-<input>
HTMLLabelElement
-<label>
HTMLLegendElement
-<legend>
HTMLLIElement
-<li>
HTMLLinkElement
-<link>
HTMLMapElement
-<map>
HTMLMediaElement
~<video>
、<audio>
HTMLMenuElement
-<menu>
HTMLMetaElement
-<meta>
HTMLMeterElement
-<meter>
HTMLModElement
~<del>
、<ins>
HTMLObjectElement
-<object>
HTMLOListElement
-<ol>
HTMLOptGroupElement
~<optgroup>
HTMLOptionElement
-<option>
HTMLOutputElement
-<output>
HTMLPictureElement
-<picture>
HTMLProgressElement
-<progress>
HTMLQuoteElement
~<q>
、<blockquote>
、<cite>
HTMLScriptElement
-<script>
HTMLSelectElement
-<select>
HTMLSlotElement
-<slot>
HTMLSourceElement
-<source>
HTMLStyleElement
~<style>
HTMLTableCellElement
~<th>
、<td>
HTMLTableColElement
~<colgroup>
、<col>
HTMLTableElement
-<table>
HTMLTableRowElement
-<tr>
HTMLTableSectionElement
~<thead>
、<tbody>
、<tfoot>
HTMLTemplateElement
-<template>
HTMLTextAreaElement
-<textarea>
HTMLTimeElement
-<time>
HTMLTitleElement
-<title>
HTMLTrackElement
-<track>
HTMLVideoElement
-<video>
命名規則は、「HTML」の後に、要素または要素のグループ(大文字のキャメルケース)が続き、その後に「要素」が続きます。ただし、要素または要素のグループ化は厳密なパターンに従っていません。このトークンをこれらを覚える必要はありません。必要なときに調べることができるよう、必ず存在を認識しておくことが重要です。
要素のコレクションがある場合は、コレクション インターフェースもあります。たとえば、HTMLCollection.namedItem()
メソッドは、id
属性または name
属性がパラメータと一致するコレクションの最初の要素を返します。どの要素も一致しない場合は null を返します。
HTMLElement
以外の 30 個を超える要素(<address>
、<article>
、<section>
、<nav>
、<header>
、<footer>
、<aside>
、<hgroup>
など)には DOM インターフェースが関連付けられていません。非推奨ではないグローバル属性をサポートしていない多くの要素には、HTMLPElement
(<p>
要素)、HTMLUnknownElement
(<😃>
、または定義されていないその他の要素など)固有のインターフェースがありますが、これらのインターフェースは HTMLElement
から継承されたプロパティとメソッドに加えて追加のプロパティやメソッドを実装しません(上記以外)。
冗長な API メソッドとプロパティ
インターフェースのメソッド名またはプロパティ名が継承されるインターフェースと同じ場合、継承されたメソッドまたはプロパティは継承しているメソッドまたはプロパティで上書きされます。上記の alt
プロパティと offsetHeight
プロパティにそれぞれ imageInstance.alt
と sectionInstance.offsetHeight
を使用してアクセスしたとき、アクセスされている API をコードは識別できませんでした。
一般的に、これら 2 つの例と同様に、これは問題ではありません。そういう場合もあります。たとえば、HTMLCollection.length
は読み取り専用ですが、継承している HTMLOptionsCollection
インターフェースの長さプロパティ(<select>
の options
プロパティによってのみ返される)を使用してコレクション サイズを設定することもできます。
その他のインターフェース
DOM ノードの分岐位置の操作を可能にする追加のインターフェースがあります。addEventListener()
と removeEventListener()
を提供する EventTarget
インターフェースは、Node
インターフェースと Window
インターフェースに継承されます。次に、Element、Document、DocumentFragment(カスタム要素で説明した)インターフェースは Node を継承し、HTMLElement インターフェースは Element を継承します。
node
インターフェース
すべてのタイプの DOM ノードは、Node
に基づくインターフェースによって表されます。このインターフェースは、要素が DOM ツリーに関連する場合に情報とメソッドを提供します。Node
インターフェースを使用すると、ノードツリーに対するクエリ実行とノードの追加が可能になります。
Douglas Crockford の有名な「Walk the DOM」関数では、Node の firstChild
プロパティと nextSibling
プロパティを使用しています。
const walk_the_DOM = function walk(node, callback) {
callback(node);
node = node.firstChild;
while (node) {
walk(node, callback);
node = node.nextSibling;
}
};
カスタム要素の定義には、Node の appendChild()
メソッドと cloneNode()
メソッドを使用しました。Node インターフェースには、DOM のクエリと操作を行うための便利なプロパティとメソッドが数多く用意されています。
customElements.define('star-rating',
class extends HTMLElement {
constructor() {
super(); // Always call super first in constructor
const starRating = document.getElementById('star-rating-template').content;
const shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.appendChild(starRating.cloneNode(true));
}
});
attachShadow()
メソッドは、要素インターフェースのメソッドです。ドキュメントのメインの DOM ツリーとは別にレンダリングされる Shadow DOM API 用の shadowRoot
インターフェースもあります。
Document
インターフェースと HTMLDocument
インターフェース
Document
インターフェースは Node
を継承します。これは、ドキュメントが HTML、SVG、XML、MathML などのいずれであっても、ブラウザに読み込まれたウェブページを表します。また、Document
インターフェースは HTMLDocument
インターフェースを継承します。
document
を使用すると、ノードタイプにすばやくアクセスし、特定の要素タイプ(document.body
や document.styleSheets
など)のコレクションを作成できます。HTMLDocument を使用すると、Document.location
、Document.lastModified
、Document.Cookie
など、HTML ノードにないドキュメントに関連する情報にアクセスできます。
Drag and Drop API や FullScreen API など、ドキュメント インターフェースを通じて表示される機能に基づいて、いくつかの API を利用できます。どちらも Element
から継承します。
Window
インターフェース
Window インターフェースには、DOM の操作に使用できる、DOM 以外にもグローバルに利用可能なアイテムが含まれています。Window には、MDN の JavaScript と DOM リファレンスに記載されている関数、名前空間、オブジェクト、コンストラクタが用意されています。
Window インターフェースは、ドキュメントを含むオブジェクトに対する API です。グローバル window
オブジェクトは、スクリプトが実行されているウィンドウです。すべてのブラウザタブには、独自の Window オブジェクトが含まれます。ウィンドウ インターフェースは、ウィンドウ全体とデバイス全体だけでなく、タブの内容もクエリできます。たとえば、resizeTo()
メソッドを使用してブラウザ ウィンドウのサイズを変更でき、devicePixelRatio
プロパティを使用すると、デバイスのディスプレイ ピクセルにアクセスできます。タブが表示される DOM ツリーではなく、コンテンツが存在するタブに関する情報にアクセスする場合、ウィンドウが目的のインターフェースである可能性が高いです。
Web Worker や IndexedDB API など、Window インターフェースを通じて表示される機能に基づいて、いくつかの API が利用できます。
理解度をチェックする
HTML API に関する知識をテストします。
DOM の O は何を表していますか。
コンテンツが表示されているタブに関する情報を確認するのに役立つインターフェースはどれですか。