1. 4.12 スクリプティング
      1. 4.12.1 script要素
        1. 4.12.1.1 スクリプト言語
        2. 4.12.1.2 script要素のコンテンツの制約
        3. 4.12.1.3 外部スクリプトに対するインライン文書
      2. 4.12.2 noscript要素
      3. 4.12.3 template要素
      4. 4.12.4 slot要素

4.12 スクリプティング

スクリプトは著者が文書に双方向性を追加することを許可する。

著者は、宣言型のメカニズムがしばしばより保守しやすく、かつ多くのユーザーがスクリプトを無効としているため、可能であれば、スクリプトに宣言型の代替を使用するよう推奨される。

たとえば、より詳細な情報を表示するセクションを表示または非表示にするスクリプトを使用する代わりに、details要素を使用できる。

著者はまた、スクリプトのサポートがない状態でそれらのアプリケーションが行儀よくデグレードするよう推奨される。

たとえば、著者がテーブルヘッダーにおいてリンクに動的なテーブルの再ソートを提供する場合、リンクはまたサーバーからソートされたテーブルを要求することによって、スクリプトなしで機能させることができるかもしれない。

4.12.1 script要素

Element/script

Support in all current engines.

Firefox1+SafariYesChrome1+
OperaYesEdge79+
Edge (Legacy)12+Internet ExplorerYes
Firefox Android4+Safari iOSYesChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes
カテゴリー
メタデータコンテンツ
フローコンテンツ
フレージングコンテンツ
スクリプトサポート要素
この要素を使用できるコンテキスト
メタデータコンテンツが期待される場所。
フレージングコンテンツが期待される場所。
スクリプトサポート要素が期待される場所。
コンテンツモデル
src属性が存在しない場合、type属性の値に依存するが、スクリプトの内容制限に一致しなければならない。
src属性が存在する場合、要素は空またはスクリプト文書を含むだけでなくスクリプトの内容制限に一致するかのいずれかでなければならない。
text/htmlにおけるタグ省略
どちらのタグも省略不可。
コンテンツ属性
グローバル属性
src — リソースのアドレス
type — スクリプトの種類
nomoduleモジュールスクリプトをサポートするユーザーエージェントにおける実行を防ぐ
async — フェッチの間ブロックなしで、可能な場合にスクリプトを実行する
defer — スクリプトの実行を延期する
crossorigin — 要素がcrossorigin要求を処理する方法
integritySubresource Integrityチェックで使用される整合性メタデータ[SRI]
referrerpolicy — 要素によって開始されたフェッチのためのリファラポリシー
アクセシビリティの考慮
著者向け
実装者向け
DOMインターフェイス
HTMLScriptElementを使用する。

script要素は、著者が文書に動的スクリプトおよびデータブロックを含むことを許可する。この要素は、ユーザーにコンテンツを表すものでない。

Element/script#attr-type

Support in all current engines.

Firefox1+SafariYesChrome1+
OperaYesEdge79+
Edge (Legacy)12+Internet ExplorerYes
Firefox Android4+Safari iOSYesChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes
caniuse.com table

type属性は、表されるスクリプトの型をカスタマイズを可能にする:

データブロック妥当なMIMEタイプ文字列を使用して表記されなければならない要件は、潜在的な将来の衝突を回避するための場所である。この仕様がスクリプトの追加の型をいずれ追加する場合、その追加の型は"module"値がモジュールスクリプトを表す方法のように、MIMEタイプでない何かにtype属性を設定することによってトリガーされる。現在に妥当なMIMEタイプ文字列を使用することで、将来のユーザーエージェントでさえも、データブロックが異なるスクリプトタイプとして再解釈されないことを保証する。

クラシックスクリプトおよびモジュールスクリプトは、インラインで埋め込むかsrc属性を使用する外部ファイルからインポートすることができ、これは指定された場合に使用する外部スクリプトリソースのURLを与える。srcが指定される場合、潜在的にスペースで囲まれる妥当な空でないURLでなければならない。インラインscript要素、または外部スクリプトリソースのコンテンツは、それぞれクラシックスクリプトおよびモジュールスクリプトに対するJavaScript仕様のScriptまたはModule制作物の要件に適合しなければならない。[JAVASCRIPT]

データブロックを含めるために使用される場合、データは、インラインに埋め込まれなければならず、データの形式は、type属性を使用して指定しなければならず、かつscript要素のコンテンツは、使用される形式のために定義される要件に適合しなければならない。srcasyncnomoduledefercrossoriginintegrityおよびreferrerpolicy属性を指定してはならない。

nomodule属性は、モジュールスクリプトをサポートするユーザーエージェントでスクリプトが実行されないようにする真偽属性である。これは、以下に示すように、モダンなユーザーエージェントのモジュールスクリプトと古いユーザーエージェントのクラシックスクリプトの選択的な実行を可能にする。nomodule属性をモジュールスクリプトで指定してはならない(この属性がある場合は無視される)。

Element/script#attr-async

Support in all current engines.

Firefox1+SafariYesChrome1+
OperaYesEdge79+
Edge (Legacy)12+Internet ExplorerYes
Firefox Android4+Safari iOSYesChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes
caniuse.com table

Element/script#attr-defer

Support in all current engines.

Firefox3.5+SafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer10+
Firefox Android4+Safari iOSYesChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes
caniuse.com table

asyncおよびdefer属性は、どのようにスクリプトが評価されるべきかを示す真偽属性である。クラシックスクリプトは、deferまたはasyncを指定してもよいが、src属性が存在しない限り、いずれかを指定してはならない。モジュールスクリプトasync属性を指定してもよいが、defer属性を指定してはならない。

これらの属性を使用して、スクリプトの種類によって選択できる複数の可能なモードが存在する。

クラシックスクリプトについて、async属性が存在する場合、クラシックスクリプトは、構文解析と並行してフェッチされるとすぐに(潜在的に構文解析が完了する前に)利用可能になると評価される。asyncが存在しないがdefer属性が存在する場合、クラシックスクリプトは、並行してフェッチされ、ページが解析終了したときに評価される。いずれの属性も存在しない場合、スクリプトは、両方が完了するまで解析を阻止して、すぐにフェッチされ評価される。

モジュールスクリプトについて、async属性が存在する場合、モジュールスクリプトとそのすべての依存関係は、構文解析と並行してフェッチされ、モジュールスクリプトは利用可能になるとすぐに(潜在的に構文解析が完了する前に)評価される。そうでなければ、モジュールスクリプトとその依存関係は、構文解析と並行してフェッチされ、ページが解析終了したときに評価される。(defer属性は、モジュールスクリプトに影響しない。)

これは、次の模式図にすべて要約される:

<script>のために、解析はフェッチと実行によって中断される。With <script defer>, fetching is parallel to parsing and execution takes place after all parsing has finished. And with <script async>, fetching is parallel to parsing but once it finishes parsing is interrupted to execute the script. <script type=のストーリーは<script defer>に似ているが、依存関係もフェッチされ、<script type="module" async>のストーリーは追加の依存関係のフェッチを伴う<script async>に似ている。">

これら属性の正確な処理の詳細は、主に歴史的な理由から、いくぶん自明でない、多くのHTMLの側面を含む。したがって、実装要求は必然的に仕様のあらゆる場所に散在している。(この節の)下記のアルゴリズムは、この処理の中核を説明するが、これらのアルゴリズムが参照する、およびHTMLにおけるscript開始タグと終了タグに対する構文解析規則、無関係なコンテンツでXMLでdocument.write()メソッドに対する規則、スクリプトの取り扱いなどによって参照される。

たとえasync属性が指定されても、デフォルトとなるブロッキング動作の代わりにdeferの動作をフォールバックするために、deferのみをサポートする(かつasyncをサポートしない)レガシーウェブブラウザーをもたらすため、defer属性は指定されてもよい。

crossorigin属性はCORS設定属性である。クラシックスクリプトについて、スクリプトが他の生成元から得られる場合、エラー情報が公開されるかどうかを制御する。モジュールスクリプトについて、クロスオリジンのリクエストに使用される資格情報モードを制御する。

クラシックスクリプトとは異なり、モジュールスクリプトは、クロスオリジンフェッチのためにCORSプロトコルを使用する必要がある。

integrity属性は、この要素が責任を負うリクエストに対する完全性メタデータを表す。値はテキストである。src属性が指定されていない場合、integrity属性は指定してはならない。[SRI]

referrerpolicy属性は、リファラポリシー属性である。その目的は、スクリプトをフェッチするときに使用されるリファラポリシーと、そこからインポートされたスクリプトを設定することにある。[REFERRERPOLICY]

インポートされたスクリプトをフェッチするときに使用されているが他のサブリソースを取得していないときに使用されているscriptのリファラポリシーの例:

<script referrerpolicy="origin">
  fetch('/api/data');    // not fetched with <script>'s referrer policy
  import('./utils.mjs'); // is fetched with <script>'s referrer policy ("origin" in this case)
</script>

srctypenomoduleasyncdefercrossoriginintegrityおよびreferrerpolicyを動的に変更する属性は直接的な影響はない。これらの属性は、下記の特定の時間でのみ使用される。

script . text [ = value ]

要素の子テキストコンテンツを返す。

与えられた値を持つ要素の子を置換するために、設定できる。

document.write()メソッドを使用して挿入するとき、通常はscript要素が実行される(一般に、スクリプトの実行またはHTMLの解析をブロックする)。innerHTML属性とouterHTML属性を使用して挿入する場合、それらは一切実行されない。

次の例において、2つのscript要素が使用される。1つは外部のクラシックスクリプトを埋め込み、もう1つはデータブロックのようないくつかのデータを含む。

<script src="game-engine.js"></script>
<script type="text/x-game-map">
........U.........e
o............A....e
.....A.....AAA....e
.A..AAA...AAAAA...e
</script>

この場合のデータは、ビデオゲームのマップを生成するスクリプトによって使用されるかもしれない。しかし、データはそのように使用する必要はない。おそらく実際にマップデータは、ページのマークアップの他の部分に埋め込まれており、ここでデータブロックは、ゲームマップで特定の機能を探しているユーザーを支援するサイトの検索エンジンによって単に使用される。

次のサンプルは、script要素が外部モジュールスクリプトを含めるために使用される方法を示す。また、フォームの出力を初期化する場合に、文書が解析されている間にscript要素がスクリプトを呼び出すために使用されうる方法を示す。

<script>
 function calculate(form) {
   var price = 52000;
   if (form.elements.brakes.checked)
     price += 1000;
   if (form.elements.radio.checked)
     price += 2500;
   if (form.elements.turbo.checked)
     price += 5000;
   if (form.elements.sticker.checked)
     price += 250;
   form.elements.result.value = price;
 }
</script>
<form name="pricecalc" onsubmit="return false" onchange="calculate(this)">
 <fieldset>
  <legend>Work out the price of your car</legend>
  <p>Base cost: £52000.</p>
  <p>Select additional options:</p>
  <ul>
   <li><label><input type=checkbox name=brakes> Ceramic brakes (£1000)</label></li>
   <li><label><input type=checkbox name=radio> Satellite radio (£2500)</label></li>
   <li><label><input type=checkbox name=turbo> Turbo charger (£5000)</label></li>
   <li><label><input type=checkbox name=sticker> "XZ" sticker (£250)</label></li>
  </ul>
  <p>Total: £<output name=result></output></p>
 </fieldset>
 <script>
  calculate(document.forms.pricecalc);
 </script>
</form>

次のサンプルは、script要素が外部モジュールスクリプトを含めるために使用される方法を示す。

<script type="module" src="app.mjs"></script>

このモジュール、およびそのすべての依存関係(ソースファイル内のJavaScript import文を通して表現される)は、フェッチされる。一度、全体の結果としてモジュールグラフがインポートされ、かつ文書が解析を完了したら、app.mjsのコンテンツは評価される。

さらに、同じWindow内の他のscript要素からのコードがapp.mjsからモジュールをインポートする場合(たとえばimport "./app.mjs";経由で)、より早いscript要素によって作成された同じモジュールスクリプトがインポートされる。

次の例は、モダンなユーザーエージェント用のモジュールスクリプトと古いユーザーエージェント用のクラシックスクリプトを含める方法を示している:

<script type="module" src="app.mjs"></script>
<script nomodule defer src="classic-app-bundle.js"></script>

モジュールスクリプトをサポートするモダンなユーザーエージェントでは、nomodule属性を持つscript要素は無視され、"module"のtypeをもつscript要素がフェッチされ、評価される(モジュールスクリプトとして)。逆に、古いユーザーエージェントは、"module"のtypeをもつscript要素を、そのスクリプトタイプを未知のものとして無視するが、nomodule属性を実装しないため、他のscript要素を(クラシックスクリプトとして)フェッチして評価することは問題ない。

次のサンプルは、​​script要素が(たとえばニュースサイト上で)より面白い読書体験を生み出すために、文書のテキストで多数の置換を行うインラインモジュールスクリプトを書くために使用することができる方法を示す:[XKCD1288]

<script type="module">
 import { walkAllTextNodeDescendants } from "./dom-utils.mjs";

 const substitutions = new Map([
   ["witnesses", "these dudes I know"]
   ["allegedly", "kinda probably"]
   ["new study", "Tumblr post"]
   ["rebuild", "avenge"]
   ["space", "spaaace"]
   ["Google glass", "Virtual Boy"]
   ["smartphone", "Pokédex"]
   ["electric", "atomic"]
   ["Senator", "Elf-Lord"]
   ["car", "cat"]
   ["election", "eating contest"]
   ["Congressional leaders", "river spirits"]
   ["homeland security", "Homestar Runner"]
   ["could not be reached for comment", "is guilty and everyone knows it"]
 ]);

 function substitute(textNode) {
   for (const [before, after] of substitutions.entries()) {
     textNode.data = textNode.data.replace(new RegExp(`\\b${before}\\b`, "ig"), after);
   }
 }

 walkAllTextNodeDescendants(document.body, substitute);
</script>

モジュールスクリプトを使用して得られたいくつかの注目すべき機能は、他のJavaScriptモジュール、デフォルトでstrictモード、およびトップレベル宣言がグローバルオブジェクトに新しいプロパティを導入しない方法から関数をインポートする機能を含む。両方の文書の解析が完了し、およびその依存関係(dom-utils.mjs)がフェッチされかつ評価されるまで、このscript要素が文書に表示されるかを問わず、評価されないことにも注意する。

4.12.1.1 スクリプト言語

サーバーはJavaScriptリソースにtext/javascriptを使用すべきである。サーバーは、JavaScriptリソースに他のJavaScript MIMEタイプを使用すべきではなく、非JavaScript MIMEタイプを使用してはならない。

4.12.1.2 script要素のコンテンツの制約

この節で説明される多少奇妙な制約を回避する最も簡単で安全な方法は、以下のシーケンスが(たとえば文字列、正規表現、またはコメントなど)スクリプト内でリテラルに表示され、かつ式の中でこのような構造体を使用してコードを記述を避けるようにするときに、"<!--"を"<\!--"として、"<script"を"<\script"として、および"</script"を"<\/script"として常にエスケープすることである。この節の制限がトリガーになりやすい落とし穴を回避する:すなわち、歴史的な理由のために、HTMLにおけるscriptブロックの解析は、これらのシーケンスを考えた場合に直観的でない働きをする奇妙で風変わりな慣習である。

script要素の子孫テキストコンテンツは、Unicodeの文字セットである次のABNFのscript生成物と一致しなければならない。[ABNF]

script        = outer *( comment-open inner comment-close outer )

outer         = < any string that doesn't contain a substring that matches not-in-outer >
not-in-outer  = comment-open
inner         = < any string that doesn't contain a substring that matches not-in-inner >
not-in-inner  = comment-close / script-open

comment-open  = "<!--"
comment-close = "-->"
script-open   = "<" s c r i p t tag-end

s             =  %x0053 ; U+0053 LATIN CAPITAL LETTER S
s             =/ %x0073 ; U+0073 LATIN SMALL LETTER S
c             =  %x0043 ; U+0043 LATIN CAPITAL LETTER C
c             =/ %x0063 ; U+0063 LATIN SMALL LETTER C
r             =  %x0052 ; U+0052 LATIN CAPITAL LETTER R
r             =/ %x0072 ; U+0072 LATIN SMALL LETTER R
i             =  %x0049 ; U+0049 LATIN CAPITAL LETTER I
i             =/ %x0069 ; U+0069 LATIN SMALL LETTER I
p             =  %x0050 ; U+0050 LATIN CAPITAL LETTER P
p             =/ %x0070 ; U+0070 LATIN SMALL LETTER P
t             =  %x0054 ; U+0054 LATIN CAPITAL LETTER T
t             =/ %x0074 ; U+0074 LATIN SMALL LETTER T

tag-end       =  %x0009 ; U+0009 CHARACTER TABULATION (tab)
tag-end       =/ %x000A ; U+000A LINE FEED (LF)
tag-end       =/ %x000C ; U+000C FORM FEED (FF)
tag-end       =/ %x0020 ; U+0020 SPACE
tag-end       =/ %x002F ; U+002F SOLIDUS (/)
tag-end       =/ %x003E ; U+003E GREATER-THAN SIGN (>)

script要素がスクリプト文書を含む場合、以下の節で記述されるように、要素のコンテンツのさらなる制約がある。

以下のスクリプトは、この問題を示している。このように、文字列が含まれているスクリプトがあるとする:

var example = 'Consider this string: <!-- <script>';
console.log(example);

これがscriptブロックで直接この文字列を入れていた場合、上記の制限に違反しない。

<script>
  var example = 'Consider this string: <!-- <script>';
  console.log(example);
</script>

しかし、より大きな問題かつ、スクリプトがそれらの制限に違反しない理由は、実際にスクリプトが奇妙に解析されるだろうということである。上記のスクリプトブロックは終了していない。それは、実際には依然としてscriptブロックの一部であるこのスニペットにおいて"</script>"終了タグのように見えるものである。(スクリプトが終了していないため)スクリプトは実行しない。スクリプトが何らかの形で実行した場合、以下のようにマークアップが見えた場合、(ここで強調される)スクリプトが妥当なJavaScriptでないので、スクリプトは失敗するだろう:

<script>
  var example = 'Consider this string: <!-- <script>';
  console.log(example);
</script>
<!-- despite appearances, this is actually part of the script still! -->
<script>
 ... // this is the same script block still...
</script>

ここで起こっていることはレガシーな理由のために、HTMLにおけるscript要素で"<!--"および"<script"文字列は、パーサーがブロックを閉じる検討するためにバランスをとる必要がある。

この節の最初に述べたように、問題の文字列をエスケープすることによって、問題は完全に回避されている:

<script>
  // Note: `\s` is an escape sequence for `s`.
  var example = 'Consider this string: <\!-- <\script>';
  console.log(example);
</script>
<!-- this is just a comment between script blocks -->
<script>
 ... // this is a new script block
</script>

次の例のように、これらのシーケンスは自然にスクリプト式で出現可能である:

if (x<!--y) { ... }
if ( player<script ) { ... }

このような場合、文字はエスケープすることはできないが、シーケンスが発生しないように式は次のように書き換えることができる:

if (x < !--y) { ... }
if (!--y > x) { ... }
if (!(--y) > x) { ... }
if (player < script) { ... }
if (script > player) { ... }

これを行うとはまた、同様に様々な落とし穴を回避する:関連する歴史的な理由のために、クラシックスクリプトで文字列"<!--"は、"//"のように、実際には行コメントの開始として扱われる。

4.12.1.3 外部スクリプトに対するインライン文書

script要素のsrc属性が指定される場合、もしあれば、script要素のコンテンツは、要素のコンテンツから分割されるようなtext IDL属性値でなければならず、文字セットがUnicodeである下記のABNFでdocumentation生成物と一致しなければならない。[ABNF]

documentation = *( *( space / tab / comment ) [ line-comment ] newline )
comment       = slash star *( not-star / star not-slash ) 1*star slash
line-comment  = slash slash *not-newline

; characters
tab           = %x0009 ; U+0009 CHARACTER TABULATION (tab)
newline       = %x000A ; U+000A LINE FEED (LF)
space         = %x0020 ; U+0020 SPACE
star          = %x002A ; U+002A ASTERISK (*)
slash         = %x002F ; U+002F SOLIDUS (/)
not-newline   = %x0000-0009 / %x000B-10FFFF
                ; a scalar value other than U+000A LINE FEED (LF)
not-star      = %x0000-0029 / %x002B-10FFFF
                ; a scalar value other than U+002A ASTERISK (*)
not-slash     = %x0000-002E / %x0030-10FFFF
                ; a scalar value other than U+002F SOLIDUS (/)

これは、JavaScriptのコメントで要素のコンテンツを設置するものと一致する。

この要求は、script要素のコンテンツの構文上に先の制約に加えて存在する。

以下は、依然として外部スクリプトファイルを参照する間に文書内で、著者がライセンス情報やAPI情報のような文書を含むことを許可する。src属性を提供する一方で、偶然にも著者が有効なスクリプトのように見えるものが含まないように、構文は制約される。

<script src="cool-effects.js">
 // create new instances using:
 //    var e = new Effect();
 // start the effect using .play, stop using .stop:
 //    e.play();
 //    e.stop();
</script>

4.12.2 noscript要素

Element/noscript

Support in all current engines.

Firefox1+SafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet ExplorerYes
Firefox Android4+Safari iOSYesChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes
カテゴリー
メタデータコンテンツ
フローコンテンツ
フレージングコンテンツ
この要素を使用できるコンテキスト
先祖noscript要素が存在しない場合、HTML文書head要素内。
先祖noscript要素が存在しない場合、HTML文書フレージングコンテンツが期待される場所。
コンテンツモデル
スクリプトが無効の場合、head要素内で:任意の順で、0個以上のlink要素、ゼロ個以上のstyle要素、0個以上のmeta要素。
スクリプトが無効の場合、head要素外で:透過的。ただし、noscript要素の子孫を持ってはならない。
そうでなければ:文で与えられる要件に適合するテキスト。
text/htmlにおけるタグ省略
どちらのタグも省略不可。
コンテンツ属性
グローバル属性
アクセシビリティの考慮
著者向け
実装者向け
DOMインターフェイス
HTMLElementを使用する。

noscript要素は、スクリプトが有効である場合は何も表さず、スクリプトが無効である場合は要素の子を表す。これは、文書が解析される方法に影響を与えることによって、スクリプトをサポートするユーザーエージェントとサポートしないユーザーエージェントに異なるマークアップを提示するために使用される。

HTML文書で使用する場合、許可されるコンテンツモデルは次のとおり:

スクリプトが無効である場合、head要素内のnoscript要素に対して

noscript要素は、linkstyle、およびmeta要素のみを含まなければならない。

スクリプトが有効である場合、head要素内のnoscript要素に対して

noscript要素は、テキストのみを含まなければならない。ただし、context要素としてnoscript要素をもつHTML断片解析アルゴリズムを呼び出すものかつinputのようなテキストコンテンツがnoscript要素の子であった場合、linkstylemeta要素のみからなるノードのリストをもたらさなければならない場合を除く。そして解析エラーでない。

スクリプトが無効である場合、head要素外のnoscript要素に対して

noscript要素のコンテンツモデルは透過的であり、同時にnoscript要素がnoscript要素を持ってはならない(noscript要素を入れ子にできない)追加制限がある。

スクリプトが有効である場合、head要素外のnoscript要素に対して

noscript要素はテキストのみを含まなければならない。ただしテキストは、以下のアルゴリズムがnoscript要素およびscript要素をもたない適合文書をもたらすものでなければならず、アルゴリズムでステップは例外を投げるまたはHTMLパーサー解析エラーを起こさないようにしなければならない:

  1. 文書からすべてのscript要素を取り除く。
  2. 文書においてすべてのnoscript要素のリストを作る。そのリストの各noscript要素に対して、以下のステップを実行する:
    1. snoscript要素要素の子テキストコンテンツとする。
    2. noscript要素のouterHTML属性をsの値に設定する。(これは、副作用としてnoscript要素を文書から除去させる。)[DOMPARSING]

歴史的な理由により、パーサーが呼び出されたときにスクリプトが有効にされたかどうかに基づくHTMLパーサーによってnoscript要素が異なる方法で処理されるので、これらのすべてのこじつけが必要とされる。

noscriptXML文書で使用してはならない。

noscript要素はHTML構文でのみ有効だが、XML構文では効果がない。スクリプトが有効である場合、この要素が動作する方法は、基本的にパーサーを"オフ"にすることであり、要素の内容は、実際の要素としてではなく純粋にテキストとして扱われているのである。XMLは、これを実行するためのメカニズムを定義しない。

次の例において、noscript要素は、スクリプトのフォールバックを提供するために使用される。

<form action="calcSquare.php">
 <p>
  <label for=x>Number</label>:
  <input id="x" name="x" type="number">
 </p>
 <script>
  var x = document.getElementById('x');
  var output = document.createElement('p');
  output.textContent = 'Type a number; it will be squared right then!';
  x.form.appendChild(output);
  x.form.onsubmit = function () { return false; }
  x.oninput = function () {
    var v = x.valueAsNumber;
    output.textContent = v + ' squared is ' + v * v;
  };
 </script>
 <noscript>
  <input type=submit value="Calculate Square">
 </noscript>
</form>

スクリプトが無効である場合、ボタンは、サーバー側で計算を行うために表示される。スクリプトが有効である場合、代わりに値がその場で計算される。

noscript要素は鈍器である。時には、スクリプトを有効にするかもしれないが、何らかの理由でページのスクリプトが失敗するかもしれない。このような理由から、次の例のように、noscript要素の使用を避ける代わりに、その場でスクリプトのないページからスクリプト化されたページにページを変更するスクリプトを設計することが一般により良い:

<form action="calcSquare.php">
 <p>
  <label for=x>Number</label>:
  <input id="x" name="x" type="number">
 </p>
 <input id="submit" type=submit value="Calculate Square">
 <script>
  var x = document.getElementById('x');
  var output = document.createElement('p');
  output.textContent = 'Type a number; it will be squared right then!';
  x.form.appendChild(output);
  x.form.onsubmit = function () { return false; }
  x.oninput = function () {
    var v = x.valueAsNumber;
    output.textContent = v + ' squared is ' + v * v;
  };
  var submit = document.getElementById('submit');
  submit.parentNode.removeChild(submit);
 </script>
</form>

上記の手法は、noscriptが許可されていないため、XML文書でも役に立つ。

4.12.3 template要素

Element/template

Support in all current engines.

Firefox22+Safari8+Chrome26+
Opera15+Edge79+
Edge (Legacy)13+Internet ExplorerNo
Firefox Android22+Safari iOS8+Chrome Android26+WebView AndroidYesSamsung Internet1.5+Opera Android?
caniuse.com table
カテゴリー
メタデータコンテンツ
フローコンテンツ
フレージングコンテンツ
スクリプトサポート要素
この要素を使用できるコンテキスト
メタデータコンテンツが期待される場所。
フレージングコンテンツが期待される場所。
スクリプトサポート要素が期待される場所。
span属性を持たないcolgroup要素の子として。
コンテンツモデル
Nothing(明確化のために、例を参照)。
text/htmlにおけるタグ省略
どちらのタグも省略不可。
コンテンツ属性
グローバル属性
アクセシビリティの考慮
著者向け
実装者向け
DOMインターフェイス
HTMLTemplateElementを使用する。

template要素は、複製され、スクリプトによって文書に挿入できるHTMLの断片を宣言するために使用される。

レンダリングにおいて、template要素は何も表さない。

template要素のテンプレートコンテンツは、要素自体の子ではない

DOM操作の結果として、template要素がTextノードと要素ノードを含むことも可能である。しかし、この要素のコンテンツモデルはnothingとして定義されるため、すべてのものはtemplate要素のコンテンツモデルに違反する。

たとえば、次の文書を考えてみる:

<!doctype html>
<html lang="en">
 <head>
  <title>Homework</title>
 <body>
  <template id="template"><p>Smile!</p></template>
  <script>
   let num = 3;
   const fragment = document.getElementById('template').content.cloneNode(true);
   while (num-- > 1) {
     fragment.firstChild.before(fragment.firstChild.cloneNode(true));
     fragment.firstChild.textContent += fragment.lastChild.textContent;
   }
   document.body.appendChild(fragment);
  </script>
</html>

templateにおけるp要素は、DOM内のtemplateの子ではないtemplate要素のcontent IDL属性によって返されるDocumentFragmentの子である。

スクリプトがtemplate要素のappendChild()を呼び出すと、(他の要素の場合と同様に)template要素に子要素が追加される。しかし、そのようにすることは、template要素のコンテンツモデルに違反することになる。

template . content

HTMLTemplateElement/content

Support in all current engines.

Firefox22+Safari8+Chrome26+
Opera15+Edge79+
Edge (Legacy)13+Internet ExplorerNo
Firefox Android22+Safari iOS8+Chrome Android26+WebView AndroidYesSamsung Internet1.5+Opera AndroidYes

テンプレートコンテンツDocumentFragment)を返す。

この例において、スクリプトは、手動でマークアップから構造を生成する代わりに要素構造を提供するためにtemplateを使用して、データ構造からデータをもつテーブル4列に投入する。

<!DOCTYPE html>
<html lang='en'>
<title>Cat data</title>
<script>
 // Data is hard-coded here, but could come from the server
 var data = [
   { name: 'Pillar', color: 'Ticked Tabby', sex: 'Female (neutered)', legs: 3 },
   { name: 'Hedral', color: 'Tuxedo', sex: 'Male (neutered)', legs: 4 },
 ];
</script>
<table>
 <thead>
  <tr>
   <th>Name <th>Color <th>Sex <th>Legs
 <tbody>
  <template id="row">
   <tr><td><td><td><td>
  </template>
</table>
<script>
 var template = document.querySelector('#row');
 for (var i = 0; i < data.length; i += 1) {
   var cat = data[i];
   var clone = template.content.cloneNode(true);
   var cells = clone.querySelectorAll('td');
   cells[0].textContent = cat.name;
   cells[1].textContent = cat.color;
   cells[2].textContent = cat.sex;
   cells[3].textContent = cat.legs;
   template.parentNode.appendChild(clone);
 }
</script>

この例は、templateのコンテンツにcloneNode()を使用する。それは、同じことをするdocument.importNode()を等価的に使用することもできる。ノード文書が更新されるときに、この2つのAPIの唯一の違いがある。ノードがappendChild()で付加される場合にcloneNode()とともに更新され、ノードがクローン化されるときに、document.importNode()とともに更新される。

4.12.4 slot要素

Element/slot

Support in all current engines.

Firefox63+Safari10+Chrome53+
Opera40+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android63+Safari iOS10+Chrome Android53+WebView Android53+Samsung Internet6.0+Opera Android41+
カテゴリー
フローコンテンツ
フレージングコンテンツ
この要素を使用できるコンテキスト
フレージングコンテンツが期待される場所。
コンテンツモデル
透過的
text/htmlにおけるタグ省略
どちらのタグも省略不可。
コンテンツ属性
グローバル属性
name — シャドウツリースロットの名前
アクセシビリティの考慮
著者向け
実装者向け
DOMインターフェイス
HTMLSlotElementを使用する。

slot要素は、スロットを定義する。典型的にシャドウツリーに使用される。もしあれば、slot要素はその割り当てられるノード表し、そうでなければそのコンテンツを表す。

nameコンテンツ属性は、任意の文字列値を含んでもよい。これはスロット名前を表す。

slot属性は、別の要素にスロットを割り当てるために使用される:name属性をもつslot要素は、その要素がそのname属性の値と一致する値を持つslot属性を持ち、かつslot要素がその対応するslot属性値を持つルートホストを持つシャドウツリーの子である場合、任意の要素が割り当てられる名前付きスロットを作成する。

slot . name

HTMLSlotElement/name

Support in all current engines.

Firefox63+Safari10.1+Chrome53+
Opera40+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android63+Safari iOS10.3+Chrome Android53+WebView Android53+Samsung Internet6.0+Opera Android41+
slot名前を取得し設定することが可能である。
slot . assignedNodes()

HTMLSlotElement/assignedNodes

Support in all current engines.

Firefox63+Safari10.1+Chrome53+
Opera40+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android63+Safari iOS10.3+Chrome Android53+WebView Android53+Samsung Internet6.0+Opera Android41+
slot割り当てられるノードを返す。
slot . assignedNodes({ flatten: true })
もしあれば、slot割り当てられるノードを返し、そうでなければslotの子を返し、かつslot要素が存在しなくなるまで、再帰的に、slot要素に遭遇するのと同じものを返す。
slot . assignedElements()

HTMLSlotElement/assignedElements

Firefox66+Safari?Chrome65+
OperaYesEdge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android66+Safari iOS?Chrome Android65+WebView Android65+Samsung Internet9.0+Opera AndroidYes
要素に限定された、slot割り当てられたノードを返す。
slot . assignedElements({ flatten: true })
要素に限定されたassignedNodes({ flatten: true })と同じものを返す。

name IDL属性は、同じ名前のコンテンツ属性を反映しなければならない。

呼び出される場合、assignedNodes(options)メソッドは次の手順を実行しなければならない:

  1. optionsflattenメンバーの値がfalseである場合、この要素の割り当てられたノードを返す。

  2. Return the result of finding flattened slottables with this element.

The assignedElements(options) method, when invoked, must run these steps:

  1. If the value of options's flatten member is false, then return this element's assigned nodes, filtered to contain only Element nodes.

  2. Return the result of finding flattened slottables with this element, filtered to contain only Element nodes.