このシリーズの冒頭で、「HTML 要素は ドキュメント オブジェクト モデルを構成するノードである」と説明しました。要素ノードのタイプについて説明しました。このセクションでは、これらのノードのクエリを可能にする要素 API について説明します。
DOM と AOM
DOM は、ドキュメントにアクセスして操作するための API です。DOM は、ドキュメント内のすべてのノードのツリーです。ノードによっては子を持つことができ、そうでないノードもあります。ツリーには、要素とその属性、テキストノードが含まれます。
ブラウザ ツールでは、上記のようなツリー可視化は提供されていませんが、要素インスペクタでノードを確認できます。
ブラウザのデベロッパー ツールで検査できるツリー表現は、ユーザー補助ツリーです。AOM は DOM に基づいています。同様に、ユーザー補助ツリーには、すべてのマークアップ要素、属性、テキストノードを表すオブジェクトが含まれています。
HTML Element API
DOM の中間の文字は「object」です。ほとんどのオブジェクト指向プログラミングの入門クラスで紹介される 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
は Element から継承し、すべての 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
-<audio>
、<video>
HTMLMenuElement
-<menu>
HTMLMetaElement
-<meta>
HTMLMeterElement
-<meter>
HTMLModElement
-<ins>
、<del>
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
-<td>
、<th>
HTMLTableColElement
-<col>
、<colgroup>
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 を返します。
30 を超える要素には、HTMLElement
以外の DOM インターフェースが関連付けられていません(<address>
、<article>
、<section>
、<nav>
、<header>
、<footer>
、<aside>
、<hgroup>
など)。非推奨ではないがグローバルではない属性をサポートしていない要素の多くには、HTMLPElement
(<p>
要素)や HTMLUnknownElement
(<😃>
または定義されていない他の要素)などの要素固有のインターフェースがありますが、これらのインターフェースは HTMLElement
から継承されたプロパティとメソッドの上に追加のプロパティやメソッドを実装しておらず、上記に記載されていません。
冗長な API メソッドとプロパティ
インターフェースに、継承するインターフェースと同じメソッド名またはプロパティ名が含まれている場合、継承元のメソッドまたはプロパティが上書きされます。つまり、親のメソッドとプロパティは子をオーバーライドします。HTML 要素 API の alt
プロパティと offsetHeight
プロパティにそれぞれ imageInstance.alt
と sectionInstance.offsetHeight
でアクセスしたとき、コードはどの API にアクセスしているかを特定しませんでした。通常、これらの 2 つの例と同様に、これは問題ではありません。
ただし、冗長性が問題になる場合もあります。たとえば、HTMLCollection.length
は読み取り専用ですが、継承インターフェース HTMLOptionsCollection
には、読み取り / 書き込みアクセス権を持つ長さプロパティ(<select>
の options
プロパティによってのみ返される)があります。HTMLOptionsCollection
を使用して、コレクション サイズを設定できます。
その他のインターフェース
DOM ノードのブランチ位置を操作できる追加のインターフェースもあります。addEventListener()
と removeEventListener()
を提供する EventTarget
インターフェースは、Node
インターフェースと Window
インターフェースに継承されます。一方、Element、Document、DocumentFragment(カスタム要素で説明しました)のインターフェースは Node から継承され、HTMLElement インターフェースは Element から継承されます。
node
インターフェース
すべてのタイプの DOM ノードは、Node
に基づくインターフェースで表されます。このインターフェースは、DOM ツリーに関連する要素として情報とメソッドを提供します。Node
インターフェースを使用すると、ノードのクエリとノードのツリーへのノードの追加が可能になります。
Douglas Crockford の有名な「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()
メソッドは Element インターフェースのメソッドです。また、ドキュメントのメイン DOM ツリーとは別にレンダリングされる Shadow DOM API の shadowRoot
インターフェースもあります。
Document
インターフェースと HTMLDocument
インターフェース
Document
インターフェースは Node
から継承します。ドキュメントが HTML、SVG、XML、MathML など、ブラウザに読み込まれたウェブページを表します。Document
インターフェースは HTMLDocument
インターフェースも継承します。
document
を使用すると、ノードタイプにすばやくアクセスし、document.body
や document.styleSheets
などの特定の要素タイプのコレクションを作成できます。HTMLDocument を使用すると、HTML ノードには存在しないドキュメントに関連する情報(Document.location
、Document.lastModified
、Document.Cookie
など)にアクセスできます。
ドキュメント インターフェースで表示される機能に基づいて、Drag and Drop API や FullScreen API など、いくつかの API を使用できます。どちらも Element
から継承しています。
Window
インターフェース
Window インターフェースには、DOM の操作に使用できる DOM 以外のグローバルに利用可能なアイテムが含まれています。Window には、MDN の JavaScript と DOM リファレンスに記載されている関数、名前空間、オブジェクト、コンストラクタが用意されています。
Window インターフェースは、ドキュメントを含むオブジェクトの API です。グローバル window
オブジェクトは、スクリプトが実行されているウィンドウです。すべてのブラウザタブには独自の Window オブジェクトが含まれています。Window インターフェースでは、タブのコンテンツだけでなく、ウィンドウとデバイス全体をクエリできます。たとえば、resizeTo()
メソッドを使用してブラウザ ウィンドウのサイズを変更できます。devicePixelRatio
プロパティを使用すると、デバイスのディスプレイ ピクセルにアクセスできます。タブに表示されている DOM ツリーではなく、コンテンツが含まれているタブに関する情報にアクセスする場合は、ウィンドウが目的のインターフェースである可能性があります。
Window インターフェースで公開される機能に基づいて、Web Workers API や IndexedDB API など、いくつかの API を使用できます。
理解度を確認する
HTML API に関する知識をテストします。
DOM の O は何を表していますか。
コンテンツが含まれているタブに関する情報を確認するには、どのインターフェースを使用すればよいですか。