4.13. ~custom要素
4.13.1. 序論
◎非規範的`~custom要素$は、 “全装備な” ~DOM要素を自前で築く仕方を作者に供する。 作者は常に,[ 標準でない要素を自身の文書に利用して, ~appに特有な挙動を~scripting等が起きた後に追加する ]こともできたが、 そのような要素は,歴史的に不適合とされてきており,機能~面でも劣る。 ~custom要素を`定義-$することにより、 作者は,[ 要素を適正に構築する方法 ]および[ その~classに属する要素が変化に対しどう反応すべきか ]を構文解析器に伝えれるようになる。 ◎ Custom elements provide a way for authors to build their own fully-featured DOM elements. Although authors could always use non-standard elements in their documents, with application-specific behavior added after the fact by scripting or similar, such elements have historically been non-conforming and not very functional. By defining a custom element, authors can inform the parser how to properly construct an element and how elements of that class should react to changes.
~custom要素は、[ (標準な~HTML要素の様な) 既存の~platform特能 ]を[ (~custom要素~定義の様な) より低~levelな,作者に公開される拡張能~地点 ]を通して説明することにより, より大きな “~platformを合理化する” 労の一環を成す。 今日の~custom要素の能力には,まだ多くの制限があり、 ~HTMLの既存の要素の挙動を — 機能, 意味論の両面で — 全部的には説明できないが、 この隔たりは,時を経れば埋められるものと希望されている。 ◎ Custom elements are part of a larger effort to "rationalise the platform", by explaining existing platform features (like the elements of HTML) in terms of lower-level author-exposed extensibility points (like custom element definition). Although today there are many limitations on the capabilities of custom elements—both functionally and semantically—that prevent them from fully explaining the behaviors of HTML's existing elements, we hope to shrink this gap over time.
4.13.1.1. 自律的~custom要素の作成-法
◎非規範的`自律的~custom要素$の作成-法を例で~~説明するため、 ここでは,小さな国旗~icon( `flag-icon^e )の描画を~capsule化する~custom要素を定義してみる。 目標は、 次の様な利用を可能にすることである: ◎ For the purposes of illustrating how to create an autonomous custom element, let's define a custom element that encapsulates rendering a small icon for a country flag. Our goal is to be able to use it like so:
<flag-icon country="nl"></flag-icon>
これを行うため、 先ず,~custom要素~用に `HTMLElement$I を拡張する~classを宣言する: ◎ To do this, we first declare a class for the custom element, extending HTMLElement:
class FlagIcon extends HTMLElement { constructor() { super(); this._countryCode = null; } static observedAttributes = ["country"]; attributeChangedCallback(%name, %oldValue, %newValue) { /* %name は常に, `observedAttributes^c が返す結果のどれか(ここでは `country^l のみ) ◎ name will always be "country" due to observedAttributes */ this._countryCode = %newValue; this._updateRendering(); } connectedCallback() { this._updateRendering(); } get country() { return this._countryCode; } set country(%v) { this.setAttribute("country", %v); } _updateRendering() { /* 読者への宿題として残しておく。 が,おそらく、 `this.ownerDocument.defaultView^m で挿入-先の文書が`属する閲覧~文脈$の有無を検査して, 無いなら何もしないことが求まれるであろう。 ◎ Left as an exercise for the reader. But, you'll probably want to check this.ownerDocument.defaultView to see if we've been inserted into a document with a browsing context, and avoid doing any work if not. */ } }
次に,この~classを利用して要素を定義する必要がある: ◎ We then need to use this class to define the element:
`customElements$m.define("flag-icon", FlagIcon);
この時点で、 上の~codeは働くことになる。 構文解析器は、 `flag-icon^e ~tagに出会う度に,[ `FlagIcon^jt ~classの新たな~instanceを構築して, その新たな `country^c 属性について上の~codeに伝えてくる ]ことになる — ~codeは、 それを利用して当の要素の内部~状態を設定し, (適切なときは)要素の描画も更新する。 ◎ At this point, our above code will work! The parser, whenever it sees the flag-icon tag, will construct a new instance of our FlagIcon class, and tell our code about its new country attribute, which we then use to set the element's internal state and update its rendering (when appropriate).
`flag-icon^e 要素を~DOM~APIを利用して作成することもできる: ◎ You can also create flag-icon elements using the DOM API:
const %flagIcon = document.createElement("flag-icon") %flagIcon.country = "jp" document.body.appendChild(%flagIcon)
最後に,`~custom要素~構築子$自身を利用して作成することもできる。 すなわち、 上の~codeは,次と等価になる: ◎ Finally, we can also use the custom element constructor itself. That is, the above code is equivalent to:
const %flagIcon = new FlagIcon() %flagIcon.country = "jp" document.body.appendChild(%flagIcon)
4.13.1.2. ~formに所有され得る~custom要素の作成-法
◎非規範的`自律的~custom要素$は、[ ~T 値を返す静的な `formAssociated^c ~prop ]を追加すれば,`~formに所有され得る~custom要素$になる。 `ElementInternals$I ~interfaceは、 作者が~form~control要素に共通な各種[ 関数, ~prop ]を実装し易くする。 ◎ Adding a static formAssociated property, with a true value, makes an autonomous custom element a form-associated custom element. The ElementInternals interface helps you to implement functions and properties common to form control elements.
class MyCheckbox extends HTMLElement {
static formAssociated = true;
static observedAttributes = ['checked'];
constructor() {
super();
this._internals = this.attachInternals();
this.addEventListener('click', this._onClick.bind(this));
}
get form() { return this._internals.form; }
get name() { return this.getAttribute('name'); }
get type() { return this.localName; }
get checked() { return this.hasAttribute('checked'); }
set checked(%flag) { this.toggleAttribute('checked', Boolean(%flag)); }
attributeChangedCallback(%name, %oldValue, %newValue) {
/*
%name は常に, `observedAttributes^c が返す結果のどれか(ここでは `checked^l のみ)
◎
name will always be "checked" due to observedAttributes
*/
this._internals.setFormValue(this.checked ? 'on' : null);
}
_onClick(%event) {
this.checked = !this.checked;
}
}
`customElements$m.define('my-checkbox', MyCheckbox);
作者は、 組込みの`~formに所有され得る要素$の様に, ~custom要素 `my-checkbox^e を利用できる。 例えば、 `my-checkbox^e 要素を `form$e 内に置けば それが`~form所有者$になり, `label$e 内に置けば その`~label先~control$になる — 当の `form$e が提出されるときには、 `my-checkbox^e の実装が供する~dataが送信されるようになる。 ◎ You can use the custom element my-checkbox like a built-in form-associated element. For example, putting it in form or label associates the my-checkbox element with them, and submitting the form will send data provided by my-checkbox implementation.
<form action="..." method="..."> <label><my-checkbox name="agreed"></my-checkbox> I read the agreement.</label> <input type="submit"> </form>
4.13.1.3. 既定の~access可能な~role, 状態, ~propを伴う~custom要素の作成-法
◎非規範的`ElementInternals$I の適切な~propを利用すれば、 ~custom要素は,既定の~accessibility意味論を有せるようになる。 次の~codeは、 前~節の~formに所有され得る~checkboxを拡げて,その既定の[ ~role/~check有無 ]を — ~accessibility技術から見て適正に — 設定する: ◎ By using the appropriate properties of ElementInternals, your custom element can have default accessibility semantics. The following code expands our form-associated checkbox from the previous section to properly set its default role and checkedness, as viewed by accessibility technology:
class MyCheckbox extends HTMLElement {
static formAssociated = true;
static observedAttributes = ['checked'];
constructor() {
super();
this._internals = this.attachInternals();
this.addEventListener('click', this._onClick.bind(this));
this._internals.role = 'checkbox';
this._internals.ariaChecked = 'false';
}
get form() { return this._internals.form; }
get name() { return this.getAttribute('name'); }
get type() { return this.localName; }
get checked() { return this.hasAttribute('checked'); }
set checked(%flag) { this.toggleAttribute('checked', Boolean(%flag)); }
attributeChangedCallback(%name, %oldValue, %newValue) {
/*
%name は常に, `observedAttributes^c が返す結果のどれか(ここでは `checked^l のみ)
◎
name will always be "checked" due to observedAttributes
*/
this._internals.setFormValue(this.checked ? 'on' : null);
this._internals.ariaChecked = this.checked;
}
_onClick(%event) {
this.checked = !this.checked;
}
}
customElements.define('my-checkbox', MyCheckbox);
組込みの要素と同様に、 これらは既定でしかないことに注意 — ~page作者は、[ `role$a 属性, 各種 `aria-*$a 属性 ]を利用して,それを上書きできる: ◎ Note that, like for built-in elements, these are only defaults, and can be overridden by the page author using the role and aria-* attributes:
<!--
この~markupは不適合
◎
This markup is non-conforming
-->
<input type="checkbox" checked role="button" aria-checked="false">
<!--
この~markupは、
おそらく,~custom要素の作者が意図したものではない
◎
This markup is probably not what the custom element author intended
-->
<my-checkbox role="button" checked aria-checked="false">
~custom要素の作者は、 当の要素の~accessibility意味論を成す各~側面のうち,どれが強い~native意味論を有するか — すなわち,~custom要素の利用者は上書きするべきでないか — を言明することが奨励される。 上の例では, `my-checkbox^e 要素の作者は、 その[ `~role$, `aria-checked$a 値 ]は強い~native意味論を有するものと言明することになろう — したがって,上のような~codeは忌避される。 ◎ Custom element authors are encouraged to state what aspects of their accessibility semantics are strong native semantics, i.e., should not be overridden by users of the custom element. In our example, the author of the my-checkbox element would state that its role and aria-checked values are strong native semantics, thus discouraging code such as the above.
4.13.1.4. ~custom化された組込みの要素の作成-法
◎非規範的`~custom化された組込みの要素$は、 別種の`~custom要素$であり,その定義は少しばかり異なる。 また、 その利用は,`自律的~custom要素$に比較してかなり異なる。 それが存在するのは、[ 新たな~custom機能性で拡張する ]ことにより[ 既存の~HTML要素の挙動 ]の再利用を許容するためである。 この再利用は重要になる — あいにく,~HTML要素の既存の挙動の多くは、 純粋に`自律的~custom要素$だけでは~~再現できないので。 代わりに,`~custom化された組込みの要素$では、[ 構築~時に~customな挙動を~installすること, 【!*】~lifecycle~hook, 既存の要素への~prototype~chain ]が許容され、 本質的に,これらの能力を既存の要素の上層に “mix-in” する。 ◎ Customized built-in elements are a distinct kind of custom element, which are defined slightly differently and used very differently compared to autonomous custom elements. They exist to allow reuse of behaviors from the existing elements of HTML, by extending those elements with new custom functionality. This is important since many of the existing behaviors of HTML elements can unfortunately not be duplicated by using purely autonomous custom elements. Instead, customized built-in elements allow the installation of custom construction behavior, lifecycle hooks, and prototype chain onto existing elements, essentially "mixing in" these capabilities on top of the already-existing element.
`~custom化された組込みの要素$には、 `自律的~custom要素$とは別個な構文が要求される — ~UAや他の~softwareは、 当の要素の[ 意味論, 挙動 ]を要素の`局所~名$elで識別しているので。 すなわち、[ 既存の挙動の上層に,`~custom化された組込みの要素$の概念を築く ]ためには,[ 拡張された要素が自身の元の局所~名を維持する ]ことが不可欠になる。 ◎ Customized built-in elements require a distinct syntax from autonomous custom elements because user agents and other software key off an element's local name in order to identify the element's semantics and behavior. That is, the concept of customized built-in elements building on top of existing behavior depends crucially on the extended elements retaining their original local name.
次の例では、[ `plastic-button^e と命名された`~custom化された組込みの要素$ ]を作成する。 それは,通常の~buttonの様に挙動するが、 ~click時には気の利いた~animation効果が追加される。 前と同様,~classを定義する所から始めるが、 今度は, `HTMLElement$I でなく `HTMLButtonElement$I を拡張する: ◎ In this example, we'll be creating a customized built-in element named plastic-button, which behaves like a normal button but gets fancy animation effects added whenever you click on it. We start by defining a class, just like before, although this time we extend HTMLButtonElement instead of HTMLElement:
class PlasticButton extends HTMLButtonElement {
constructor() {
super();
this.addEventListener("click", () => {
/*
何か気の利いた~animation効果を描く
◎
Draw some fancy animation effects!
*/
});
}
}
上のような~custom要素を定義するときには、 `extends$mb ~optionも指定する必要がある: ◎ When defining our custom element, we have to also specify the extends option:
`customElements$m.define("plastic-button", PlasticButton, { extends: "button" });
一般に,どの名前の要素を拡張しているかは、 どの要素~interfaceを拡張しているか見るだけでは決定できない。 多くの要素は、 同じ~interfaceを共有しているので (例: `q$e と `blockquote$e は `HTMLQuoteElement$I を共有している)。 ◎ In general, the name of the element being extended cannot be determined simply by looking at what element interface it extends, as many elements share the same interface (such as q and blockquote both sharing HTMLQuoteElement).
構文解析される~HTML~source~textから`~custom化された組込みの要素$を構築するためには、 `is$a 属性を利用する — ここでは, `button$e 要素~上で: ◎ To construct our customized built-in element from parsed HTML source text, we use the is attribute on a button element:
<button `is$a="plastic-button">Click Me!</button>
`~custom化された組込みの要素$を`自律的~custom要素$として利用するよう試行しても、 `働かない^em。 すなわち、 `<plastic-button>Click me?</plastic-button>^c は、 単純に[ 特別な挙動を何も伴わない `HTMLElement$I ]を作成することになる。 ◎ Trying to use a customized built-in element as an autonomous custom element will not work; that is, <plastic-button>Click me?</plastic-button> will simply create an HTMLElement with no special behavior.
~custom化された組込みの要素を~program的に作成する必要がある場合、 `createElement()$m を次のような形で利用できる: ◎ If you need to create a customized built-in element programmatically, you can use the following form of createElement():
const %plasticButton = document.createElement("button", { is: "plastic-button" }); %plasticButton.textContent = "Click me!";
構築子も、 前と同じく働くことになる: ◎ And as before, the constructor will also work:
const %plasticButton2 = new PlasticButton();
console.log(%plasticButton2.localName); /*
`button^l と出力される
◎
will output "button"
*/
console.assert(%plasticButton2 instanceof PlasticButton);
console.assert(%plasticButton2 instanceof HTMLButtonElement);
~custom化された組込みの要素を~program的に作成した場合、 `is$a 属性は,明示的に設定されてないので~DOM内には無い — しかしながら、 `直列化-時には出力に追加される@~HTMLwriting#attr-is-during-serialization$: ◎ Note that when creating a customized built-in element programmatically, the is attribute will not be present in the DOM, since it was not explicitly set. However, it will be added to the output when serializing:
console.assert(!%plasticButton.hasAttribute("is"));
console.log(%plasticButton.outerHTML); /*
`<button is="plastic-button"></button>^l
と出力される
◎
will output '<button is="plastic-button"></button>'
*/
それがどう作成されたかに関わらず, `button$e に備わる特別なふるまい — ~focus時の挙動, `~form提出$に関与する能, `disabled$a 属性, 等々 — すべては、この種の “`plastic^en な~button” にも適用される。 ◎ Regardless of how it is created, all of the ways in which button is special apply to such "plastic buttons" as well: their focus behavior, ability to participate in form submission, the disabled attribute, and so on.
`~custom化された組込みの要素$は、 既存の~HTML要素を[ ~UAが給する有用な挙動や~APIが備わる ]よう拡張できるように設計された。 そのようなわけで、 拡張できるのは[ この仕様に定義される既存の~HTML要素 ]に限られる。 次に挙げる旧来の要素 — `要素~interface$として `HTMLUnknownElement$I を利用するものと定義された要素 — は拡張できない ⇒ `applet$eO†, `bgsound$eO, `blink$eO, `isindex$eO, `keygen$eO, `multicol$eO, `nextid$eO, `spacer$eO ◎ Customized built-in elements are designed to allow extension of existing HTML elements that have useful user-agent supplied behavior or APIs. As such, they can only extend existing HTML elements defined in this specification, and cannot extend legacy elements such as bgsound, blink, isindex, keygen, multicol, nextid, or spacer that have been defined to use HTMLUnknownElement as their element interface.
【† `applet^eO は、この訳による補完。 】
この要件がある理由には、 将来との互換性もある。 仮に,`~custom化された組込みの要素$が現在は未知な要素 — 例えば `combobox^e とする — を拡張するように定義された場合、 そのように派生された要素の消費者たちは[ その基底~要素 `combobox^e は,~UAが給する挙動に関わらないこと ]に依存するようになり, この仕様が将来に `combobox^e 要素を定義できなくなる。 ◎ One reason for this requirement is future-compatibility: if a customized built-in element was defined that extended a currently-unknown element, for example combobox, this would prevent this specification from defining a combobox element in the future, as consumers of the derived customized built-in element would have come to depend on their base element having no interesting user-agent-supplied behavior.
4.13.1.5. 自律的~custom要素の欠点
◎非規範的以下に指定されるとおり,および上で~~示唆したように、 単純に[ `taco-button^e と称される要素を定義して利用した ]としても,[ その種の要素が~buttonを`表現-$する ]ことにはならない。 すなわち、[ ~web~browser, 探索~engine, ~accessibility技術 ]などの~toolは、 結果の要素を,単に[ 定義された名前に基づいて,自動的に~buttonとして扱う ]ことにはならない。 ◎ As specified below, and alluded to above, simply defining and using an element called taco-button does not mean that such elements represent buttons. That is, tools such as web browsers, search engines, or accessibility technology will not automatically treat the resulting element as a button just based on its defined name.
`自律的~custom要素$を利用しつつ,[ 様々な利用者から欲される,~buttonの意味論 ]を伝達するためには、 いくつかの技法を使役する必要がある: ◎ To convey the desired button semantics to a variety of users, while still using an autonomous custom element, a number of techniques would need to be employed:
- `tabindex$a 属性を追加すれば、 `taco-button^e 要素は`~focus可能$になる。 この場合、 `taco-button^e が論理的に不能化されたときには, `tabindex$a 属性も除去する必要があることに注意。 ◎ The addition of the tabindex attribute would make the taco-button focusable. Note that if the taco-button were to become logically disabled, the tabindex attribute would need to be removed.
- ~ARIA~role, および各種~ARIA[ 状態/~prop ]を追加すれば、 意味論を~accessibility技術に伝達する一助になる。 例えば,`~role$を `button$l に設定すれば、[ “要素は~buttonである” という意味論を伝達する ]ことになり,[ 利用者が,~accessibility技術の下で、 通例の~buttonの様に,当の~controlとヤリトリすること ]を可能化する。 また, `aria-label$a ~propを設定して、 当の~buttonに`~access可能な名前$を与えることも必要yである — さもなければ,~accessibility技術は、 子~text~nodeたちを辿って,それらを発声することになる。 また,~buttonが論理的に不能化されたときには、 `aria-disabled$a 状態を `true^l に設定すれば, その不能化d状態は~accessibility技術へ伝達される。 ◎ The addition of an ARIA role and various ARIA states and properties helps convey semantics to accessibility technology. For example, setting the role to "button" will convey the semantics that this is a button, enabling users to successfully interact with the control using usual button-like interactions in their accessibility technology. Setting the aria-label property is necessary to give the button an accessible name, instead of having accessibility technology traverse its child text nodes and announce them. And setting the aria-disabled state to "true" when the button is logically disabled conveys to accessibility technology the button's disabled state.
- ~buttonに共通的に期待される挙動を取扱うために~event~handlerを追加することも、 ~web~browser利用者に~buttonの意味論を伝達する一助になる。 この事例で最も関連な~event~handlerは、適切な `keydown$et ~eventを代理して, `click$et ~event化するものになるであろう — そうすれば、~keyboardでも~clickでも,~buttonを作動化できるようになるので。 ◎ The addition of event handlers to handle commonly-expected button behaviors helps convey the semantics of the button to web browser users. In this case, the most relevant event handler would be one that proxies appropriate keydown events to become click events, so that you can activate the button both with keyboard and by clicking.
- 既定で供される視覚的な~style付けに加えて、 `taco-button^e 要素は, 論理的な状態~変化 — 不能化される( `disabled^a 属性)など — を反映するときにも更新される必要がある。 すなわち、 ~stylesheet内にある `taco-button^e 用の規則には, それが何であれ `taco-button[disabled]^css 用の規則も必要になる。 ◎ In addition to any default visual styling provided for taco-button elements, the visual styling will also need to be updated to reflect changes in logical state, such as becoming disabled; that is, whatever style sheet has rules for taco-button will also need to have rules for taco-button[disabled].
これらの点を念頭に、[ ~button意味論を伝達する責務を担う,全装備な `taco-button^e ](不能化される能も含む)は,次の様な見かけの何かになろう: ◎ With these points in mind, a full-featured taco-button that took on the responsibility of conveying button semantics (including the ability to be disabled) might look something like this:
class TacoButton extends HTMLElement {
static observedAttributes = ["disabled"];
constructor() {
super();
this._internals = this.attachInternals();
this._internals.role = "button";
this.addEventListener("keydown", %e => {
if (%e.code === "Enter" || %e.code === "Space") {
this.dispatchEvent(new PointerEvent("click", {
bubbles: true,
cancelable: true
}));
}
});
this.addEventListener("click", %e => {
if (this.disabled) {
%e.preventDefault();
%e.stopImmediatePropagation();
}
});
this._observer = new MutationObserver(() => {
this._internals.ariaLabel = this.textContent;
});
}
connectedCallback() {
this.setAttribute("tabindex", "0");
this._observer.observe(this, {
childList: true,
characterData: true,
subtree: true
});
}
disconnectedCallback() {
this._observer.disconnect();
}
get disabled() {
return this.hasAttribute("disabled");
}
set disabled(%flag) {
this.toggleAttribute("disabled", Boolean(%flag));
}
attributeChangedCallback(%name, %oldValue, %newValue) {
/*
%name は常に, `observedAttributes^c が返す結果のどれか(ここでは `disabled^l のみ)
◎
name will always be "disabled" due to observedAttributes
*/
if (this.disabled) {
this.removeAttribute("tabindex");
this._internals.ariaDisabled = "true";
} else {
this.setAttribute("tabindex", "0");
this._internals.ariaDisabled = "false";
}
}
}
このそれなりに複雑な要素~定義をもってしても、 要素は,消費者にとって利用するのは楽でない: それは、 そいつの意志で `tabindex$a を “不断に生やし続ける” ことになり、 それが選んだ `tabindex="0"^c に対する~focus能の挙動は, 現在の~platformにおける~buttonの挙動に合致しないこともあろう。 このことは、 今の所,~custom要素~用には既定の[ ~focus時の挙動 ]を指定する仕方がなく、 そうするためには, `tabindex$a 属性の利用を強いられるからである (それは、通例的には[ 消費者が既定の挙動を上書きする ]ためとして予約されるにもかかわらず)。 ◎ Even with this rather-complicated element definition, the element is not a pleasure to use for consumers: it will be continually "sprouting" tabindex attributes of its own volition, and its choice of tabindex="0" focusability behavior may not match the button behavior on the current platform. This is because as of now there is no way to specify default focus behavior for custom elements, forcing the use of the tabindex attribute to do so (even though it is usually reserved for allowing the consumer to override default behavior).
対照的に,前~節に示した単純な`~custom化された組込みの要素$は、 `button$e 要素の[ 意味論, 挙動 ]を自動的に継承することになるので, これらの挙動を手動で実装する必要はない。 一般に、[ 自明でない[ 意味論, 挙動 ]を伴う,~HTMLの既存の要素 ]の上層に築かれる どの要素~用にも, `~custom化された組込みの要素$の方が[ 開発する, 保守する, 消費する ]のは容易になる。 ◎ In contrast, a simple customized built-in element, as shown in the previous section, would automatically inherit the semantics and behavior of the button element, with no need to implement these behaviors manually. In general, for any elements with nontrivial behavior and semantics that build on top of existing elements of HTML, customized built-in elements will be easier to develop, maintain, and consume.
4.13.1.6. 要素の作成~後の昇格~法
◎非規範的`要素~定義$は,いつでも生じさせ得るので、 ~customでない要素を`作成して@~DOM4#concept-create-element$から,後で — 適切な`~custom要素~定義$が登録された後に — `~custom要素$になるようにすることもできる。 この処理nは、 通常の要素から~custom要素への “昇格ng” と呼ばれる。 ◎ Because element definition can occur at any time, a non-custom element could be created, and then later become a custom element after an appropriate definition is registered. We call this process "upgrading" the element, from a normal element into a custom element.
`~custom要素~定義$を登録するのは、 それに関連な要素が初期~時に — 構文解析器などにより — 作成された後の方が,好ましいこともある。 `昇格$は、 そのような~~用法を可能化して,[ ~custom要素の内容を漸進的に増強する ]ことを許容する。 例えば、 次の~HTML文書と `img-viewer^e 用の要素~定義は, 非同期的に読込まれる: ◎ Upgrades enable scenarios where it may be preferable for custom element definitions to be registered after relevant elements have been initially created, such as by the parser. They allow progressive enhancement of the content in the custom element. For example, in the following HTML document the element definition for img-viewer is loaded asynchronously:
<!DOCTYPE html> <html lang="ja"> <title>画像~viewerの例</title> <img-viewer filter="Kelvin"> <img src="images/tree.jpg" alt="何もないサバンナにそびえる美しい木"> </img-viewer> <script src="js/elements/img-viewer.js" async></script>
ここでの `img-viewer^e 要素~用の定義は、[ ~markup内の `<img-viewer>^c ~tagの後に置かれた, `async$a 属性を有する `script$e 要素 ]を利用して読込まれる。 ~scriptを読込んでいる間、 `img-viewer^e 要素は,[ `span$e に類似な,未定義な要素 ]として扱われることになる。 ~scriptが読込まれ,それが `img-viewer^e 要素を定義したとき、 ~page上の既存の `img-viewer^e 要素は,[ その~custom要素~定義が適用され,昇格される ]ことになる (それは、 文字列 `Kelvin^l で識別される画像~filterを適用して, 画像の視覚的な外観を増強することが~~想定されている)。 ◎ The definition for the img-viewer element here is loaded using a script element marked with the async attribute, placed after the <img-viewer> tag in the markup. While the script is loading, the img-viewer element will be treated as an undefined element, similar to a span. Once the script loads, it will define the img-viewer element, and the existing img-viewer element on the page will be upgraded, applying the custom element's definition (which presumably includes applying an image filter identified by the string "Kelvin", enhancing the image's visual appearance).
【 `img-viewer^e の名前には~hyphenがあるので、 将来も含めて,~scriptが読込まれる前に特別な意味を持つ要素に解釈される心配はない (`妥当な~custom要素~名$を見よ)。 】
`昇格$が適用されるのは、 文書~tree内にある(正式には,`接続されて$いる)要素に限られることに注意。 文書に挿入されていない要素は、 昇格されないままになる。 この点について,例で~~説明すると: ◎ Note that upgrades only apply to elements in the document tree. (Formally, elements that are connected.) An element that is not inserted into a document will stay un-upgraded. An example illustrates this point:
<!DOCTYPE html> <html lang="en"> <title>昇格の際どい事例</title> <example-element></example-element> <script> "use strict"; const %文書内 = document.querySelector("example-element"); const %文書外 = document.createElement("example-element"); /* 要素~定義の前: どちらも `HTMLElement^I : ◎ Before the element definition, both are HTMLElement: */ console.assert(%文書内 instanceof HTMLElement); console.assert(%文書外 instanceof HTMLElement); class ExampleElement extends HTMLElement {} `customElements$m.define("example-element", ExampleElement); /* 要素~定義の後: 文書~内に在った方の要素は、 この時点で昇格-済み: ◎ After element definition, the in-document element was upgraded: */ console.assert(%文書内 instanceof ExampleElement); console.assert(!(%文書外 instanceof ExampleElement)); document.body.appendChild(%文書外); /* そうでない方の要素を文書の中に移動した後には、 それも昇格される: ◎ Now that we've moved the element into the document, it too was upgraded: */ console.assert(%文書外 instanceof ExampleElement); </script>
4.13.1.7. ~custom要素~状態の公開-法
~UAにより供される組込みの要素には、[ 利用者-ヤリトリ~その他の要因に依存して,時間~越しに変化し得る ある種の状態 ]たちがあり, `疑似類$を通して~web作者に公開される。 例えば,一部の~form~controlには、 “妥当でない” 状態があり, `invalid$ps `疑似類$を通して公開される。 ◎ Built-in elements provided by user agents have certain states that can change over time depending on user interaction and other factors, and are exposed to web authors through pseudo-classes. For example, some form controls have the "invalid" state, which is exposed through the :invalid pseudo-class.
組込みの要素と同様、 `~custom要素$も様々な状態をとり得る — `~custom要素$の作者は、 これらの状態を組込みの要素と類似な流儀で公開するよう求める。 ◎ Like built-in elements, custom elements can have various states to be in too, and custom element authors want to expose these states in a similar fashion as the built-in elements.
これは、 `state()$ps 疑似類を介して行われる。 ~custom要素の作者は、 `ElementInternals$I の `states$eI ~propを利用して, そのような~custom状態を追加したり除去できる — それらは、 `state()$ps 疑似類の引数として公開されるようになる。 ◎ This is done via the :state() pseudo-class. A custom element author can use the states property of ElementInternals to add and remove such custom states, which are then exposed as arguments to the :state() pseudo-class.
`state()$ps を利用して,~customな~checkbox要素を~styleする方法を次に示す。 `LabeledCheckbox^I は、 その “~check有無” 状態を内容~属性を介して公開しないと見做す。 ◎ The following shows how :state() can be used to style a custom checkbox element. Assume that LabeledCheckbox doesn't expose its "checked" state via a content attribute.
`custom-element-states-1^xCode~custom疑似類は、 ~shadowな各部でも~targetできる。 上の例の拡張は、 これを示す: ◎ Custom pseudo-classes can even target shadow parts. An extension of the above example shows this:
`custom-element-states-2^xCode4.13.2. ~custom要素の構築子と反応に課される要件
`~custom要素~構築子$を著作する際には、 作者には,次の適合性~要件が課される: ◎ When authoring custom element constructors, authors are bound by the following conformance requirements:
- 正しい~prototype~chain および `this^jv 値を確立するため、 `super()^c を — 他のすべての~codeが走る前に,構築子の本体を成す最初の~statementで — ~parameterなしで~callしなければナラナイ。 ◎ A parameter-less call to super() must be the first statement in the constructor body, to establish the correct prototype chain and this value before any further code is run.
- `return^c ~statementは、 単純な早期 return ( `return^c / `return this^c )でない限り, 構築子の本体に現れてはナラナイ。 ◎ A return statement must not appear anywhere inside the constructor body, unless it is a simple early-return (return or return this).
- 構築子は、[ `document.write()$m / `document.open()$m ]~methodを利用してはナラナイ。 ◎ The constructor must not use the document.write() or document.open() methods.
- 当の要素の[ 属性/子 ]を検分してはナラナイ — `昇格$がない事例では何も無く、 昇格に依拠することは,要素を利用し難いものにするので。 【?】 ◎ The element's attributes and children must not be inspected, as in the non-upgrade case none will be present, and relying on upgrades makes the element less usable.
- どの[ 属性/子 ]であれ,当の要素に持たせてはナラナイ — それは、[ `createElement()$m / `createElementNS()$m ]~methodを利用する消費者の期待に違反するので。 ◎ The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.
- 一般に、 アリな限り,作業は — とりわけ,資源の~fetchingや具現化を孕むものは — `connectedCallback()^c へ先送りされるべきである。 しかしながら, `connectedCallback()^c は複数回~callされ得ることに注意 — 初期化を行うような~~真に一度限りの作業は、 重ねて走らないよう,防護する必要がある。 ◎ In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.
- 一般に,構築子は、[ 初期~状態や既定の値,あるいは~event~listener,場合によっては`~shadow根$ ]を設定しておくために利用されるべきである。 ◎ In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.
これらの要件のうちいくつかは、 `要素を作成する$間に[ 直接的/間接的 ]に検査される。 要件に従わない場合、 ~custom要素は,構文解析器や~DOM~APIにより~instance化できなくなる。 このことは、 構築子から起動される小taskの内側で行われる作業にも該当する — `小task~checkpoint$が生じ得るのは、 構築の直後からなので。 ◎ Several of these requirements are checked during element creation, either directly or indirectly, and failing to follow them will result in a custom element that cannot be instantiated by the parser or DOM APIs. This is true even if the work is done inside a constructor-initiated microtask, as a microtask checkpoint can occur immediately after construction.
`~custom要素~反応$を著作するときには、 作者は~node~treeを操作するのを避けるベキである — それは、 予期されない結果へ至らせ得るので。 ◎ When authoring custom element reactions, authors should avoid manipulating the node tree as this can lead to unexpected results.
要素の `connectedCallback()^c は,要素が切断される前に~queueされ得るが、[ ~callback~queueがまだ処理されているため,もはや接続されていない要素 ]用の `connectedCallback()^c になる例: ◎ An element's connectedCallback can be queued before the element is disconnected, but as the callback queue is still processed, it results in a connectedCallback for an element that is no longer connected:
class CParent extends HTMLElement { connectedCallback() { this.firstChild.remove(); } } customElements.define("c-parent", CParent); class CChild extends HTMLElement { connectedCallback() { console.log("CChild connectedCallback: isConnected =", this.isConnected); } } customElements.define("c-child", CChild); const %parent = new CParent(), %child = new CChild(); parent.append(%child); document.body.append(%parent); // Logs: // CChild connectedCallback: isConnected = false
4.13.3. 中核~概念
`~custom要素@ は、 `~custom$elである要素である†。 これは,非正式には、[ その構築子と~prototypeは、 ~UAに代わって,作者により定義される ]ことを意味する。 この[ 作者が給する構築子~関数 ]は、 `~custom要素~構築子@ と呼ばれる。 ◎ A custom element is an element that is custom. Informally, this means that its constructor and prototype are defined by the author, instead of by the user agent. This author-supplied constructor function is called the custom element constructor.
【† 昇格される前は、 まだ “~customでない” 】
次に挙げる 2 つの別個な種別を成す`~custom要素$を定義できる: ◎ Two distinct types of custom elements can be defined:
- `自律的~custom要素@ ( `autonomous custom element^en ) ⇒ `extends$mb ~optionを伴わずに定義されるもの。 この種別を成す~custom要素の`局所~名$elは、 それに定義された`名前$cDに等しくなる。 ◎ An autonomous custom element, which is defined with no extends option. These types of custom elements have a local name equal to their defined name.
- `~custom化された組込みの要素@ ( `customized built-in element^en ) ⇒ `extends$mb ~optionを伴って定義されるもの。 この種別を成す~custom要素の`局所~名$elは、 当の~optionに 【当の~custom要素が拡張する要素の名前として】 渡された値に等しくなる。 それに定義された`名前$cDは、 `is@a 属性の値として利用される — したがって、 `妥当な~custom要素~名$でなければナラナイ。 ◎ A customized built-in element, which is defined with an extends option. These types of custom elements have a local name equal to the value passed in their extends option, and their defined name is used as the value of the is attribute, which therefore must be a valid custom element name.
`~custom要素$が`作成され@~DOM4#concept-create-element$た後に `is$a 属性の値を変更しても,[ `~is0値$elとして要素に保存-済みな,要素の挙動 ]は変化しない。 ◎ After a custom element is created, changing the value of the is attribute does not change the element's behavior, as it is saved on the element as its is value.
`自律的~custom要素$の`要素~定義@~HTMLdom#element-definitions$は、 次で与えられる: ◎ Autonomous custom elements have the following element definition:
- `分類$:
- `~flow内容$/`句ng内容$/`可触~内容$ ◎ Flow content. ◎ Phrasing content. ◎ Palpable content.
- `~formに所有され得る~custom要素$に限り ⇒ `~formに所有され得る要素$のうち[ `~listされる$/`~label可能$/`提出-可能$/`再設定-可能$ ]なもの ◎ For form-associated custom elements: Listed, labelable, submittable, and resettable form-associated element.
- `この要素を利用できる文脈$:
- `句ng内容$が期待される所。 ◎ Where phrasing content is expected.
- `内容~model$:
- `透過的$。 ◎ Transparent.
- `内容~属性$:
- `大域~属性$ — ただし、 `is$a 属性は除く。 ◎ Global attributes, except the is attribute
- `form$a :`~formに所有され得る~custom要素$用 — 要素を `form$e 要素に所有させる ◎ form, for form-associated custom elements — Associates the element with a form element
- `disabled$a :`~formに所有され得る~custom要素$用 — この~form~controlを不能化するかどうか ◎ disabled, for form-associated custom elements — Whether the form control is disabled
- `readonly$a :`~formに所有され得る~custom要素$用 — `willValidate$eI, および当の~custom要素の[ 作者により追加される挙動 ]に影響する。 ◎ readonly, for form-associated custom elements — Affects willValidate, plus any behavior added by the custom element author
- `name$a :`~formに所有され得る~custom要素$用 — [ `~form提出$ / `form.elements@~HEforms#dom-form-elements$c ~API ]用に利用する要素の名前 ◎ name, for form-associated custom elements — Name of the element to use for form submission and in the form.elements API
- 他の,どの名前空間にも属さない任意の属性(注釈文を見よ)。 ◎ Any other attribute that has no namespace (see prose).
- `~accessibilityの考慮点$
- `~formに所有され得る~custom要素$の場合 ⇒ `作者~向け@~HTMLARIA#el-form-associated-custom-element$/ `実装者~向け@~HTMLAAM#el-form-associated-custom-element$ ◎ For form-associated custom elements: for authors; for implementers.
- 他の場合 ⇒ `作者~向け@~HTMLARIA#el-autonomous-custom-element$/ `実装者~向け@~HTMLAAM#el-autonomous-custom-element$ ◎ Otherwise: for authors; for implementers.
- `~DOM~interface$:
- 要素の作者が給する( `HTMLElement$I を継承する)。 ◎ Supplied by the element's author (inherits from HTMLElement)
`自律的~custom要素$は、 特別な意味を有さず,その子たちを`表現-$する。 `~custom化された組込みの要素$は、 それが拡張する要素の意味論を継承する。 ◎ An autonomous custom element does not have any special meaning: it represents its children. A customized built-in element inherits the semantics of the element that it extends.
作者は、 `自律的~custom要素$に[ その機能に関連なものと決定した任意の属性 ]を指定できる — 当の属性が ~AND↓ を満たす限り:
- どの名前空間にも属さない
- その名前は、 次を満たす ⇒ [ `~XML互換$である ]~AND[ `~ASCII英大文字$を包含しない ]
ただし,例外として、 `is$a 属性は,`自律的~custom要素$に指定してはナラナイ (また、指定しても効果はない)。 ◎ The exception is the is attribute, which must not be specified on an autonomous custom element (and which will have no effect if it is).
`~custom化された組込みの要素$の属性は、 それが拡張する要素に基づく通常の要件に従う。 ~custom属性に基づく挙動を追加するためには、 【作者は】 `data-*$a 属性を利用すること。 ◎ Customized built-in elements follow the normal requirements for attributes, based on the elements they extend. To add custom attribute-based behavior, use data-* attributes.
次を満たす`自律的~custom要素$は、 `~formに所有され得る~custom要素@ と呼ばれる ⇒ それに結付けられた`~custom要素~定義$の`~formに所有され得るか$cD ~EQ ~T ◎ An autonomous custom element is called a form-associated custom element if the element is associated with a custom element definition whose form-associated field is set to true.
`~formに所有され得る~custom要素$ %要素 の: ◎ ↓
- `name$a 属性は、 %要素 の名前を表現する。 ◎ The name attribute represents the form-associated custom element's name.\
- `disabled$a 属性は、 %要素 を対話的でなくし,`提出~値$cFも提出させなくするために利用される。 ◎ The disabled attribute is used to make the form-associated custom element non-interactive and to prevent its submission value from being submitted.\
- `form$a 属性は、 %要素 の`~form所有者$を明示的に指定するために利用される。 ◎ The form attribute is used to explicitly associate the form-associated custom element with its form owner.
- `readonly@a 属性は、 【`真偽-属性$であり,在るならば】 %要素 は`拘束~検証の対象外$になるものと指定する。 ~UAは[ この属性~用には、 他の挙動は何ら供さない ]が、 ~custom要素の作者は[ この属性が在るときには、 アリな所では,当の~controlを編集-不能にする ]ベキである — 組込みの~form~controlの `readonly@~HEinput#attr-input-readonly$a 属性~用の挙動に類似な,何らかの適切な流儀で。 ◎ The readonly attribute of form-associated custom elements specifies that the element is barred from constraint validation. User agents don't provide any other behavior for the attribute, but custom element authors should, where possible, use its presence to make their control non-editable in some appropriate fashion, similar to the behavior for the readonly attribute on built-in form controls.
拘束~検証 ⇒ `~formに所有され得る~custom要素$は、 次が満たされる間は`拘束~検証の対象外$になる ⇒ `readonly$a 属性を有する ◎ Constraint validation: If the readonly attribute is specified on a form-associated custom element, the element is barred from constraint validation.
`~formに所有され得る~custom要素$ %要素 用の`再設定~algo$は、 次を走らす ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `formResetCallback^l, « » ) ◎ The reset algorithm for form-associated custom elements is to enqueue a custom element callback reaction with the element, callback name "formResetCallback", and « ».
`妥当な~custom要素~名@ は、 次の両~要件を満たす文字~並びである: ◎ A valid custom element name is a sequence of characters name that meets all of the following requirements:
-
`PotentialCustomElementName$P 生成規則に合致しなければナラナイ: ◎ name must match the PotentialCustomElementName production:
`PotentialCustomElementName@P ::=
-
[a-z] (`PCENChar$P)* '-' (`PCENChar$P)*
`PCENChar@P ::=
"-" | "." | [0-9] | "_" | [a-z] | #xB7 | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x203F-#x2040] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
この生成規則は、 `XML$r 仕様の `EBNF 記法@~TR/xml/#sec-notation$を利用している。 ◎ This uses the EBNF notation from the XML specification. [XML]
-
次に挙げるものに一致してはナラナイ: ◎ name must not be any of the following:
- `annotation-xml^l
- `color-profile^l
- `font-face^l
- `font-face-src^l
- `font-face-uri^l
- `font-face-format^l
- `font-face-name^l
- `missing-glyph^l
注記: 上に挙げた名前は、 `適用-可能な仕様$ — すなわち、 ここでは `SVG 2^cite `SVG$r, `MathML^cite `MATHMLCORE$r — に定義される要素のうち,~hyphenを包含するものすべてを要約したものである。 ◎ The list of names above is the summary of all hyphen-containing element names from the applicable specifications, namely SVG 2 and MathML. [SVG] [MATHML]
注記: これらの要件は、 次に挙げる,`妥当な~custom要素~名$の目標を確保するためにある: ◎ These requirements ensure a number of goals for valid custom element names:
- `~ASCII英小文字$から始まる — ~HTML構文解析器が[ それを~textではなく~tagとして扱う ]ことを確保するため。 ◎ They start with an ASCII lower alpha, ensuring that the HTML parser will treat them as tags instead of as text.
- `~ASCII英大文字$を包含しない — ~UAが[ ~HTML要素を常に~ASCII大小無視で扱える ]ことを確保するため。 ◎ They do not contain any ASCII upper alphas, ensuring that the user agent can always treat HTML elements ASCII-case-insensitively.
- ~hyphenを包含する — 名前空間~付けに利用するために加え、 前方-互換性も確保するため (将来において、[ ~hyphenを包含する局所~名 ]を伴う要素が[ ~HTML / ~SVG / ~MathML ]に追加されることはないので)。 ◎ They contain a hyphen, used for namespacing and to ensure forward compatibility (since no elements will be added to HTML, SVG, or MathML with hyphen-containing local names in the future).
- [ `createElement()$m / `createElementNS()$m ]でも,常に作成できるようにするため — これらには、 構文解析器によるものを超える制約がある。 ◎ They can always be created with createElement() and createElementNS(), which have restrictions that go beyond the parser's.
これらの制約は別として、 可能な限り柔軟にするため,多様な名前が許容される — `<math-α>^c や `<emotion-😍>^c の様な利用事例のために。 ◎ Apart from these restrictions, a large variety of names is allowed, to give maximum flexibility for use cases like <math-α> or <emotion-😍>.
各 `~custom要素~定義@ は、 `~custom要素$を述べる — それは、 次に挙げるものからなる: ◎ A custom element definition describes a custom element and consists of:
- `名前@cD ◎ A name
- `妥当な~custom要素~名$ ◎ A valid custom element name
- `局所~名@cD ◎ A local name
- 局所~名 ◎ A local name
- `構築子@cD ◎ A constructor
- ~IDL `CustomElementConstructor$I ~callback関数~型の値 ◎ A Web IDL CustomElementConstructor callback function type value\
- `~custom要素~構築子$を包装する。 ◎ wrapping the custom element constructor
- `観測される属性~群@cD ◎ A list of observed attributes
- `sequence<DOMString>^I 型の値 ◎ A sequence<DOMString>
- 【 観測-対象にする内容~属性たちの名前を~~保持する。 】
- `~lifecycle~callback~map@cD ◎ A collection of lifecycle callbacks
- `~map$ — 次に挙げる~keyを伴う ⇒# `connectedCallback^l, `disconnectedCallback^l, `adoptedCallback^l, `attributeChangedCallback^l, `formAssociatedCallback^l, `formDisabledCallback^l, `formResetCallback^l, `formStateRestoreCallback^l ◎ A map, whose keys are the strings "connectedCallback", "disconnectedCallback", "adoptedCallback", "attributeChangedCallback", "formAssociatedCallback", "formDisabledCallback", "formResetCallback", and "formStateRestoreCallback".\
- どの~keyに対応する値も,次のいずれかをとる ⇒# ~NULL (既定~値)/ ~IDL `Function$I ~callback関数~型の値 ◎ The corresponding values are either a Web IDL Function callback function type value, or null. By default the value of each entry is null.
- 【 これらの~callbackが いつ~callされるかは、 `§ ~custom要素~反応@#custom-element-reactions$ を見よ。 】
- `構築~stack@cD ◎ A construction stack
- ~list — 初期~時は空とする。 ◎ A list, initially empty,\
- この~listは、[ `要素を昇格する$~algo, `~HTML要素~構築子$ ]により操作される。 ◎ that is manipulated by the upgrade an element algorithm and the HTML element constructors.\
- この~listを成す各~entryは、 次のいずれかになる ⇒# ある要素, `すでに構築-済みを表す~marker@i ◎ Each entry in the list will be either an element or an already constructed marker.
- `~formに所有され得るか@cD ◎ A form-associated\
- 真偽値 ◎ boolean
- ~T ならば、 ~UAは,この`~custom要素~定義$に結付けられる要素を`~formに所有され得る~custom要素$として扱う。 ◎ If this is true, user agent treats elements associated to this custom element definition as form-associated custom elements.
- `内部特能を不能化するか@cD ◎ A disable internals\
- 真偽値 ◎ boolean
- `attachInternals()$m を制御する。 ◎ Controls attachInternals().
- `~shadowを不能化するか@cD ◎ A disable shadow\
- 真偽値 ◎ boolean
- `attachShadow()$m を制御する。 ◎ Controls attachShadow().
`~custom要素~定義を検索する@ 手続きは、所与の ( %文書, %名前空間, %局所~名, %is ) に対し,[ `~custom要素~定義$/~NULL ]を返す: ◎ To look up a custom element definition, given a document, namespace, localName, and is, perform the following steps. They will return either a custom element definition or null:
- ~IF[ %名前空間 ~NEQ `~HTML名前空間$ ] ⇒ ~RET ~NULL ◎ If namespace is not the HTML namespace, then return null.
- ~IF[ %文書 が`属する閲覧~文脈$ ~EQ ~NULL ] ⇒ ~RET ~NULL ◎ If document's browsing context is null, then return null.
- %定義~集合 ~LET %文書 に`関連な大域~obj$の`~custom要素~registry$の`~custom要素~定義~集合$ ◎ Let registry be document's relevant global object's custom element registry.object.
- ~IF[ %定義~集合 を成す~itemとして[ その`名前$cD ~EQ %局所~名 ]を満たすもの %定義 は在る ]~AND[ %定義 の`局所~名$cD ~EQ %局所~名 ] ⇒ ~RET %定義 ◎ If registry's custom element definition set contains an item with name and local name both equal to localName, then return that item.
- ~IF[ %定義~集合 を成す~itemとして[ その`名前$cD ~EQ %is ]を満たすもの %定義 は在る ]~AND[ %定義 の`局所~名$cD ~EQ %局所~名 ] ⇒ ~RET %定義 ◎ If registry's custom element definition set contains an item with name equal to is and local name equal to localName, then return that item.
- ~RET ~NULL ◎ Return null.
4.13.4. `CustomElementRegistry^I ~interface
各 `Window$I ~obj %~window には、 `~custom要素~registry@ が結付けられる — それは,ある `CustomElementRegistry$I ~objであり、 %~window が作成されるとき,新たなそれに設定される。 ◎ Each Window object has an associated custom element registry (a CustomElementRegistry object). It is set to a new CustomElementRegistry object when the Window object is created.
注記: `~custom要素~registry$を結付けるものは、 `Document$I ~objではなく, `Window$I ~objである — 各`~custom要素~構築子$は `HTMLElement$I ~interfaceを継承し, `HTMLElement$I ~interfaceは `Window$I ~objごとに正確に 1 個あるので。 ◎ Custom element registries are associated with Window objects, instead of Document objects, since each custom element constructor inherits from the HTMLElement interface, and there is exactly one HTMLElement interface per Window object.
[Exposed=Window] interface `CustomElementRegistry@I { [`CEReactions$] undefined `define$m( DOMString %name, `CustomElementConstructor$I %constructor, optional `ElementDefinitionOptions$I %options = {} ); (`CustomElementConstructor$I or undefined) `get$m(DOMString %name); DOMString? `getName$m(`CustomElementConstructor$I %constructor); `Promise$<`CustomElementConstructor$I> `whenDefined$m(DOMString %name); [`CEReactions$] undefined `upgrade$m(`Node$I %root); }; callback `CustomElementConstructor@I = `HTMLElement$I (); dictionary `ElementDefinitionOptions@I { DOMString `extends@mb; };
各 `CustomElementRegistry$I は、 次に挙げるものを有する: ◎ ↓
-
`~custom要素~定義~集合@ ⇒ `~custom要素~定義$たちが成す`集合$ — 初期~時は空とする。 この集合を成す~itemは、[ `名前$cD/`局所~名$cD/`構築子$cD ]を利用して検索される。
【 この集合を成す複数個の~itemが[ 同じ`名前$cD/同じ`構築子$cD ]を共有することはない — `define()$m ~methodが,そのことを保証する (`~custom要素~定義$が作成される機会は、 この~methodの中に限られる)。 】【 この集合を成す~itemどうしの同等性が何に基づくか定義されていないが、 `名前$cDまたは`構築子$cD(どちらでも結果は同じ)に基づくであろう。 】【 この集合から~itemを除去する (既存の`~custom要素~定義$を “無かったこと” にする) 仕方は無い (`論点@https://github.com/WICG/webcomponents/issues/754$)。 】
◎ Every CustomElementRegistry has a custom element definition set, a set of custom element definitions, initially « ». Lookup of items in this set uses their name, local name, or constructor. - `要素~定義は走っているか@ ⇒ 真偽値 — 初期~時は ~F とする。 `要素~定義$が再入的に呼出されるのを防止するためにある。 ◎ Every CustomElementRegistry also has an element definition is running boolean which is used to prevent reentrant invocations of element definition. It is initially false.
-
`定義-済み時~promise~map@ ⇒ `妥当な~custom要素~名$から~promiseへの`~map$ 【— 初期~時は空とする】。 `whenDefined()$m ~methodを実装するために利用される。 ◎ Every CustomElementRegistry also has a when-defined promise map, a map of valid custom element names to promises. It is used to implement the whenDefined() method.
【 これらの~promiseは、 `定義-済み$elになったとき`解決される@~WEBIDLjs#resolve$。 】
- %window.`customElements$m.`define(name, constructor)$m
- `名前$cD %name を伴う新たな`~custom要素$を`自律的~custom要素$として定義する。 %constructor が その構築子を与える。 %name は その構築子に対応付けられる。 ◎ Defines a new custom element, mapping the given name to the given constructor as an autonomous custom element.
- %window.`customElements$m.`define$m(%name, %constructor, { extends: %baseLocalName })
- `名前$cD %name を伴う新たな`~custom要素$を`~custom化された組込みの要素$として定義する。 %constructor が その構築子を与える。 %name は その構築子に対応付けられる。 拡張される`要素~型$は、 %baseLocalName 値で識別される。 [ `~custom要素$/未知な要素 ]を拡張するよう試行した場合、 `NotSupportedError$E 例外が投出される。 ◎ Defines a new custom element, mapping the given name to the given constructor as a customized built-in element for the element type identified by the supplied baseLocalName. A "NotSupportedError" DOMException will be thrown upon trying to extend a custom element or an unknown element.
- %window.`customElements$m.`get(name)$m
- 所与の`名前$cD( %name )用に定義された`~custom要素~構築子$を検索取得する。 `名前$cDとして %name を伴う`~custom要素~定義$は無い場合、 `undefined^jv を返す。 ◎ Retrieves the custom element constructor defined for the given name. Returns undefined if there is no custom element definition with the given name.
- %window.`customElements$m.`getName(constructor)$m
- 所与の`構築子$cD( %constructor )用に定義された`~custom要素$に与えられた名前を検索取得する。 `構築子$cDとして %constructor を伴う`~custom要素~定義$は無い場合、 ~NULL を返す。 ◎ Retrieves the given name for a custom element defined for the given constructor. Returns null if there is no custom element definition with the given constructor.
- %window.`customElements$m.`whenDefined(name)$m
- ~promiseを返す — それは、 所与の`名前$cD( %name )を伴う`~custom要素$ %要素 が`定義-済み$elになったとき, %要素 の構築子で充足されることになる (すでに定義-済みならば、 即時に充足されることになる)。 %name が`妥当な~custom要素~名$でない場合、 `却下される~promise$( `SyntaxError$E 例外 ) を返す。 ◎ Returns a promise that will be fulfilled with the custom element's constructor when a custom element becomes defined with the given name. (If such a custom element is already defined, the returned promise will be immediately fulfilled.) Returns a promise rejected with a "SyntaxError" DOMException if not given a valid custom element name.
- %window.`customElements$m.`upgrade(root)$m
- %root の`~shadowも含めた広義-子孫$である要素すべてを — `接続されて$いなくても — `昇格するよう試行する@#concept-try-upgrade$。 ◎ Tries to upgrade all shadow-including inclusive descendant elements of root, even if they are not connected.
`要素~定義@ は、 `~custom要素~定義$を `CustomElementRegistry$I に追加する処理nである。 これは、 `define()$m ~methodにより成遂げられる。 ◎ Element definition is a process of adding a custom element definition to the CustomElementRegistry. This is accomplished by the define() method.\
`define(name, constructor, options)@m ~method手続きは: ◎ The define(name, constructor, options) method steps are:
- ~IF[ `IsConstructor$jA( %constructor ) ~EQ ~F ] ⇒ ~THROW `TypeError$E ◎ If IsConstructor(constructor) is false, then throw a TypeError.
- ~IF[ %name は`妥当な~custom要素~名$でない ] ⇒ ~THROW `SyntaxError$E ◎ If name is not a valid custom element name, then throw a "SyntaxError" DOMException.
- ~IF[ コレの`~custom要素~定義~集合$を成す~itemとして[ その`名前$cD ~EQ %name ]を満たすものが在る ] ⇒ ~THROW `NotSupportedError$E ◎ If this's custom element definition set contains an item with name name, then throw a "NotSupportedError" DOMException.
- ~IF[ コレの`~custom要素~定義~集合$を成す~itemとして[ その`構築子$cD ~EQ %constructor ]を満たすものが在る ] ⇒ ~THROW `NotSupportedError$E ◎ If this's custom element definition set contains an item with constructor constructor, then throw a "NotSupportedError" DOMException.
- %局所~名 ~LET %name ◎ Let localName be name.
- %extends ~LET %options[ "`extends$mb" ] ◎ Let extends be options["extends"] if it exists; otherwise null.
-
~IF[ %extends ~NEQ ε ]: ◎ If extends is not null:
- ~IF[ %extends は`妥当な~custom要素~名$である ] ⇒ ~THROW `NotSupportedError$E ◎ If extends is a valid custom element name, then throw a "NotSupportedError" DOMException.
- ~IF[ ( %extends, `~HTML名前空間$ ) 用の`要素~interface$ ~EQ `HTMLUnknownElement$I (例: %extends は、 この仕様~内の要素~定義を指示していない) ] ⇒ ~THROW `NotSupportedError$E ◎ If the element interface for extends and the HTML namespace is HTMLUnknownElement (e.g., if extends does not indicate an element definition in this specification), then throw a "NotSupportedError" DOMException.
- %局所~名 ~SET %extends ◎ Set localName to extends.
- ~IF[ コレの`要素~定義は走っているか$ ~EQ ~T ] ⇒ ~THROW `NotSupportedError$E ◎ If this's element definition is running is true, then throw a "NotSupportedError" DOMException.
- コレの`要素~定義は走っているか$ ~SET ~T ◎ Set this's element definition is running to true.
- %~formに所有され得るか ~LET ~F ◎ Let formAssociated be false.
- %内部特能を不能化するか ~LET ~F ◎ Let disableInternals be false.
- %~shadowを不能化するか ~LET ~F ◎ Let disableShadow be false.
- %観測される属性~群 ~LET 空な `sequence<DOMString>^c ◎ Let observedAttributes be an empty sequence<DOMString>.
-
%~lifecycle~callback群 ~LET 新たな`~map$
【 これは,原文では次の段の中の入子な~block内で宣言されているが、 その後の段でも利用されるので,ここで宣言することにする。 】
◎ ↓ -
この段の中で例外が投出されたときは、 ~catchして,下に与える手続き (A) を走らす: ◎ Run the following steps while catching any exceptions:
- %~prototype ~LET ~ABRUPT `Get$jA( %constructor, `prototype^l ) ◎ Let prototype be ? Get(constructor, "prototype").
- ~IF[ %~prototype は `Object$jt でない ] ⇒ ~THROW `TypeError$E ◎ If prototype is not an Object, then throw a TypeError exception.
-
« `connectedCallback^l, `disconnectedCallback^l, `adoptedCallback^l, `attributeChangedCallback^l » を成す ~EACH( %~callback名 ) に対し: ◎ ↑ Let lifecycleCallbacks be the ordered map\ «[ "connectedCallback" → null, "disconnectedCallback" → null, "adoptedCallback" → null, "attributeChangedCallback" → null ]». ◎ For each callbackName of the keys of lifecycleCallbacks:
- %~lifecycle~callback群[ %~callback名 ] ~SET ~NULL ◎ ↑
- %~callback値 ~LET ~ABRUPT `Get$jA( %~prototype, %~callback名 ) ◎ Let callbackValue be ? Get(prototype, callbackName).
- ~IF[ %~callback値 ~NEQ `undefined^jv ] ⇒ %~lifecycle~callback群[ %~callback名 ] ~SET `~IDL値に変換する$( %~callback値, `Function$I ) ◎ If callbackValue is not undefined, then set lifecycleCallbacks[callbackName] to the result of converting callbackValue to the Web IDL Function callback type.
-
~IF[ %~lifecycle~callback群[ `attributeChangedCallback^l ] ~NEQ ~NULL ]: ◎ If lifecycleCallbacks["attributeChangedCallback"] is not null:
- %観測される属性~群の可反復 ~LET ~ABRUPT `Get$jA( %constructor, `observedAttributes^l ) ◎ Let observedAttributesIterable be ? Get(constructor, "observedAttributes").
- ~IF[ %観測される属性~群の可反復 ~NEQ `undefined^jv ] ⇒ %観測される属性~群 ~SET `~IDL値に変換する$( %観測される属性~群の可反復, `sequence<DOMString>^I ) (例外投出あり) ◎ If observedAttributesIterable is not undefined, then set observedAttributes to the result of converting observedAttributesIterable to a sequence<DOMString>. Rethrow any exceptions from the conversion.
- %不能化された特能~群 ~LET 空な `sequence<DOMString>^c ◎ Let disabledFeatures be an empty sequence<DOMString>.
- %不能化された特能~群の可反復 ~LET ~ABRUPT `Get$jA( %constructor, `disabledFeatures^l ) ◎ Let disabledFeaturesIterable be ? Get(constructor, "disabledFeatures").
- ~IF[ %不能化された特能~群の可反復 ~NEQ `undefined^jv ] ⇒ %不能化された特能~群 ~SET `~IDL値に変換する$( %不能化された特能~群の可反復, `sequence<DOMString>^I ) (例外投出あり) ◎ If disabledFeaturesIterable is not undefined, then set disabledFeatures to the result of converting disabledFeaturesIterable to a sequence<DOMString>. Rethrow any exceptions from the conversion.
- ~IF[ `internals^l ~IN %不能化された特能~群 ] ⇒ %内部特能を不能化するか ~SET ~T ◎ If disabledFeatures contains "internals", then set disableInternals to true.
- ~IF[ `shadow^l ~IN %不能化された特能~群 ] ⇒ %~shadowを不能化するか ~SET ~T ◎ If disabledFeatures contains "shadow", then set disableShadow to true.
- %~formに所有され得る値 ~LET ~ABRUPT `Get$jA( %constructor, `formAssociated^l ) ◎ Let formAssociatedValue be ? Get( constructor, "formAssociated").
- %~formに所有され得るか ~SET `~IDL値に変換する$( %~formに所有され得る値, `boolean^c ) ◎ Set formAssociated to the result of converting formAssociatedValue to a boolean.
-
« `formAssociatedCallback^l, `formResetCallback^l, `formDisabledCallback^l, `formStateRestoreCallback^l » を成す ~EACH( %~callback名 ) に対し: ◎ ↓If formAssociated is true,\ then for each of "formAssociatedCallback", "formResetCallback", "formDisabledCallback", and "formStateRestoreCallback" callbackName:
- %~lifecycle~callback群[ %~callback名 ] ~SET ~NULL 【この段は、この訳による補完。】
- ~IF[ %~formに所有され得るか ~EQ ~F ] ⇒ ~CONTINUE ◎ ↑
- %~callback値 ~LET ~ABRUPT `Get$jA( %~prototype, %~callback名 ) ◎ Let callbackValue be ? Get(prototype, callbackName).
- ~IF[ %~callback値 ~NEQ `undefined^jv ] ⇒ %~lifecycle~callback群[ %~callback名 ] ~SET `~IDL値に変換する$( %~callback値, `Function$I ) ◎ If callbackValue is not undefined, then set lifecycleCallbacks[callbackName] to the result of converting callbackValue to the Web IDL Function callback type.
- コレの`要素~定義は走っているか$ ~SET ~F ◎ ↓
(A) 上で例外 %例外 が投出されたときは: ◎ Then, regardless of whether the above steps threw an exception or not:\
- コレの`要素~定義は走っているか$ ~SET ~F ◎ set this's element definition is running to false.
- ~THROW %例外 ◎ Finally, if the steps threw an exception, rethrow that exception.
- %定義 ~LET 新たな`~custom要素~定義$ — その ⇒# `名前$cD ~SET %name, `局所~名$cD ~SET %局所~名, `構築子$cD ~SET %constructor, `観測される属性~群$cD ~SET %観測される属性~群, `~lifecycle~callback~map$cD ~SET %~lifecycle~callback群 `~formに所有され得るか$cD ~SET %~formに所有され得るか, `内部特能を不能化するか$cD ~SET %内部特能を不能化するか, `~shadowを不能化するか$cD ~SET %~shadowを不能化するか ◎ Let definition be a new custom element definition with name name, local name localName, constructor constructor, observed attributes observedAttributes, lifecycle callbacks lifecycleCallbacks, form-associated formAssociated, disable internals disableInternals, and disable shadow disableShadow.
- コレの`~custom要素~定義~集合$に %定義 を`付加する$set ◎ Append definition to this's custom element definition set.
- %文書 ~LET コレに`関連な大域~obj$に`結付けられた文書$ ◎ Let document be this's relevant global object's associated Document.
-
%昇格~候補~群 ~LET %文書 の`~shadowも含めた子孫$である要素のうち[ ~AND↓ を満たすもの ]たちが成す, `~shadowも含めた~tree順序$による~list:
- その`名前空間$el ~EQ `~HTML名前空間$
- その`局所~名$el ~EQ %局所~名
- [ %extends ~NEQ ε ]ならば、 次も満たす ⇒ その`~is0値$el ~EQ %name
- %昇格~候補~群 を成す ~EACH( 要素 %要素 ) に対し ⇒ `~custom要素~昇格~反応を~enqueueする$( %要素, %定義 ) ◎ For each element element of upgradeCandidates, enqueue a custom element upgrade reaction given element and definition.
- %~map ~LET コレの`定義-済み時~promise~map$ ◎ ↓
-
~IF[ %~map[ %name ] ~NEQ ε ]: ◎ If this's when-defined promise map[name] exists:
- `~promiseを解決する$( %~map[ %name ], %constructor ) ◎ Resolve this's when-defined promise map[name] with constructor.
- %~map[ %name ] ~SET ε ◎ Remove this's when-defined promise map[name].
`get(name)@m ~method手続きは: ◎ The get(name) method steps are:
- ~IF[ コレの`~custom要素~定義~集合$を成す~itemとして[ その`名前$cD ~EQ %name ]を満たすもの %定義 は在る ] ⇒ ~RET %定義 の`構築子$cD ◎ If this's custom element definition set contains an item with name name, then return that item's constructor.
- ~RET `undefined^jv ◎ Return undefined.
`getName(constructor)@m ~method手続きは: ◎ The getName(constructor) method steps are:
- ~IF[ コレの`~custom要素~定義~集合$を成す~itemとして[ その`構築子$cD ~EQ %constructor ]を満たすもの %定義 は在る ] ⇒ ~RET %定義 の`名前$cD ◎ If this's custom element definition set contains an item with constructor constructor, then return that item's name.
- ~RET ~NULL ◎ Return null.
`whenDefined(name)@m ~method手続きは: ◎ The whenDefined(name) method steps are:
- ~IF[ %name は`妥当な~custom要素~名$でない ] ⇒ ~RET `却下される~promise$( `SyntaxError$E 例外 ) ◎ If name is not a valid custom element name, then return a promise rejected with a "SyntaxError" DOMException.
- ~IF[ コレの`~custom要素~定義~集合$を成す~itemとして[ その`名前$cD ~EQ %name ]を満たすもの %定義 は在る ] ⇒ ~RET `解決される~promise$( %定義 の`構築子$cD ) ◎ If this's custom element definition set contains an item with name name, then return a promise resolved with that item's constructor.
- %~map ~LET コレの`定義-済み時~promise~map$ ◎ ↓
- ~IF[ %~map[ %name ] ~EQ ε ] ⇒ %~map[ %name ] ~SET `新たな~promise$ ◎ If this's when-defined promise map[name] does not exist, then set this's when-defined promise map[name] to a new promise.
- ~RET %~map[ %name ] ◎ Return this's when-defined promise map[name].
`whenDefined()$m ~methodは、 適切な`~custom要素$がすべて`定義-済み$elになるまでは, 動作が遂行されるのを避けたいときに利用できる。 次の例では、 `defined$ps 疑似類と組合せて、 利用する`自律的~custom要素$がすべて定義-済みになるまでは, 動的に読込まれる記事の内容( %articleContainer )を隠す。 ◎ The whenDefined() method can be used to avoid performing an action until all appropriate custom elements are defined. In this example, we combine it with the :defined pseudo-class to hide a dynamically-loaded article's contents until we're sure that all of the autonomous custom elements it uses are defined.
%articleContainer.hidden = true; fetch(%articleURL) .then(%response => %response.text()) .then(%text => { %articleContainer.innerHTML = %text; return Promise.all( [...%articleContainer.querySelectorAll(":not(:defined)")] .map(%el => customElements.whenDefined(%el.localName)) ); }) .then(() => { %articleContainer.hidden = false; });
`upgrade(root)@m ~method手続きは: ◎ When invoked, the upgrade(root) method must run these steps:
- %候補~群 ~LET %root の`~shadowも含めた広義-子孫$である要素たち成す, `~shadowも含めた~tree順序$による`~list$ ◎ Let candidates be a list of all of root's shadow-including inclusive descendant elements, in shadow-including tree order.
- %候補~群 を成す ~EACH( %候補 ) に対し ⇒ `要素を昇格するよう試行する$( %候補 ) ◎ For each candidate of candidates, try to upgrade candidate.
`upgrade()$m ~methodを利用すれば、 要素を意のままに昇格できる。 通常は,要素は`接続されたとき$に自動的に昇格されるが、 そうなる前に昇格する必要があるときなど。 ◎ The upgrade() method allows upgrading of elements at will. Normally elements are automatically upgraded when they become connected, but this method can be used if you need to upgrade before you're ready to connect the element.
const %el = document.createElement("spider-man"); class SpiderMan extends HTMLElement {} customElements.define("spider-man", SpiderMan); console.assert(!(%el instanceof SpiderMan)); /* まだ昇格されていない ◎ not yet upgraded */ customElements.upgrade(%el); console.assert(%el instanceof SpiderMan); /* 昇格された ◎ upgraded! */
4.13.5. 昇格
`要素を昇格する@ ときは、 所与の ( `~custom要素~定義$ %定義, 要素 %要素 ) に対し,次の手続きを走らす: ◎ To upgrade an element, given as input a custom element definition definition and an element element, run the following steps:
-
~IF[ %要素 の`~custom要素~状態$el ~NIN { `undefined^l, `uncustomized^l } ] ⇒ ~RET ◎ If element's custom element state is not "undefined" or "uncustomized", then return.
これが生じ得る局面は、 次の例に示すように,この~algoが再入的に呼出されたときである: ◎ One scenario where this can occur due to reentrant invocation of this algorithm, as in the following example:
<!DOCTYPE html> <x-foo id="a"></x-foo> <x-foo id="b"></x-foo> <script> /* `a^v, `b^v の両者に対し,昇格~反応を~enqueueするように定義する: ◎ Defining enqueues upgrade reactions for both "a" and "b" */ customElements.define("x-foo", class extends HTMLElement { constructor() { super(); const %b = document.querySelector("#b"); %b.remove(); /* `a^v, `b^v に対し この構築子が走っている間, `a^v, `b^v は依然として未定義なので、 次のように `b^v を文書の中へ挿入するときには、 `x-foo^e の定義-時に~enqueueされるものに加え,[ 2 回目の, `b^v に対する 昇格~反応 ]も~enqueueすることになる。 ◎ While this constructor is running for "a", "b" is still undefined, and so inserting it into the document will enqueue a second upgrade reaction for "b" in addition to the one enqueued by defining x-foo. */ document.body.appendChild(%b); } }) </script>
したがって,`要素を昇格する$~algoは、 2 回目の `b^v に対し呼出されたときには,この段にて 早くに抜け出ることになる。 ◎ This step will thus bail out the algorithm early when upgrade an element is invoked with "b" a second time.
- %要素 の`~custom要素~定義$el ~SET %定義 ◎ Set element's custom element definition to definition.
-
%要素 の`~custom要素~状態$el ~SET `failed^l ◎ Set element's custom element state to "failed".
注記: `昇格に成功したなら@#concept-upgrade-an-element-set-state-to-custom$, `custom^l に設定されることになるが、 今は — 再入的な呼出nが `上の段@#concept-upgrade-an-element-early-exit$で弾かれるよう — `failed^l に設定する ◎ It will be set to "custom" after the upgrade succeeds. For now, we set it to "failed" so that any reentrant invocations will hit the above early-exit step.
- %要素 の`属性~list$を成す ~EACH ( %属性 ) に対し,順に ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `attributeChangedCallback^l, « %属性 の`局所~名$attr, ~NULL, %属性 の`値$attr, %属性 の`名前空間$attr » ) ◎ For each attribute in element's attribute list, in order, enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and « attribute's local name, null, attribute's value, attribute's namespace ».
- ~IF[ %要素 は`接続されて$いる ] ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `connectedCallback^l, « » ) ◎ If element is connected, then enqueue a custom element callback reaction with element, callback name "connectedCallback", and « ».
- %定義 の`構築~stack$cDの末尾に %要素 を追加する ◎ Add element to the end of definition's construction stack.
- %C ~LET %定義 の`構築子$cD ◎ Let C be definition's constructor.
-
次に与える手続き (A), (B) を順に走らす — ただし,手続き (A) にて例外が投出されたときは、 ~catchして,手続き (B) へ~~移行する: ◎ Run the following substeps while catching any exceptions:
(A):
-
~IF[ %定義 の`~shadowを不能化するか$cD ~EQ ~T ]~AND[ %要素 の`~shadow根$el ~NEQ ~NULL ] ⇒ ~THROW `NotSupportedError$E ◎ If definition's disable shadow is true and element's shadow root is non-null, then throw a "NotSupportedError" DOMException.
注記: この段が必要になるのは、 `attachShadow()$m が`~custom要素~定義を検索する$を利用しないためである — `attachInternals()$m は、それを利用するが。 ◎ This is needed as attachShadow() does not use look up a custom element definition while attachInternals() does.
- %要素 の`~custom要素~状態$el ~SET `precustomized^l ◎ Set element's custom element state to "precustomized".
-
%構築-結果 ~LET `~callback関数で構築する$( %C, 空な引数~list ) ◎ Let constructResult be the result of constructing C, with no arguments.
%C が`不適合tに@#custom-element-conformance$ `CEReactions$xA 拡張d属性を伴う~APIを利用している場合、 この~algoの冒頭にて~enqueueされた反応は、 %C が終わってこの~algoに制御を返す前の,この段の間に実行されることになる。 他の場合、 %C と残りの昇格~処理nを終えた後に実行されることになる。 ◎ If C non-conformantly uses an API decorated with the [CEReactions] extended attribute, then the reactions enqueued at the beginning of this algorithm will execute during this step, before C finishes and control returns to this algorithm. Otherwise, they will execute after C and the rest of the upgrade process finishes.
-
~IF[ `SameValue$jA( %構築-結果 . [[value]], %要素 ) ~EQ ~F ] ⇒ ~THROW `TypeError$E ◎ If SameValue(constructResult, element) is false, then throw a TypeError.
注記: これが生じ得るのは、 %C が次のいずれかに該当する場合である:
- `super()^c を~callする前に, 同じ~custom要素の別の~instanceを構築している
- 構築子から任意な `HTMLElement$I ~objを返すような, ~JS による `return^c を上書きする特能を利用している
(B): ◎ Then, perform the following substep, regardless of whether the above steps threw an exception or not:
-
%定義 の`構築~stack$cDから最後の~entryを除去する ◎ Remove the last entry from the end of definition's construction stack.
注記: %C が `super()^c を~callして(`適合t@#custom-element-conformance$ならば そうすることになる), かつ その~callが成功した場合、 除去される~entryは,[ この~algoの冒頭で~pushされた) %要素 ]を置換した, `すでに構築-済みを表す~marker$i になる(`~HTML要素~構築子$がこの置換を行う)。 ◎ Assuming C calls super() (as it will if it is conformant), and that the call succeeds, this will be the already constructed marker that replaced the element we pushed at the beginning of this algorithm. (The HTML element constructor carries out this replacement.)
そうでない場合 ( `super()^c を~callしなかった(すなわち,適合しない)か, `~HTML要素~構築子$が例外を投出した場合)、 この~entryは依然として %要素 のままになる。 ◎ If C does not call super() (i.e. it is not conformant), or if any step in the HTML element constructor throws, then this entry will still be element.
-
~IF[ 上の (A) にて例外が投出された ]: ◎ Finally, if the above steps threw an exception, then:
- %要素 の`~custom要素~定義$el ~SET ~NULL ◎ Set element's custom element definition to null.
- %要素 の`~custom要素~反応~queue$を空にする ◎ Empty element's custom element reaction queue.
- ~THROW 投出された例外 ◎ Rethrow the exception (thus terminating this algorithm).
注記: 上の手続きで例外が投出された場合、 %要素 の`~custom要素~状態$elは[ `failed^l / `precustomized^l ]であり続けることになる。 ◎ If the above steps threw an exception, then element's custom element state will remain "failed" or "precustomized".
-
-
~IF[ %要素 は`~formに所有され得る~custom要素$である ]: ◎ If element is a form-associated custom element, then:
- `~form所有者を設定し直す$( %要素 ) ◎ Reset the form owner of element.\
- ~IF[ %要素 の`~form所有者$ ~NEQ ~NULL ] ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `formAssociatedCallback^l, « %要素 の`~form所有者$ » ) ◎ If element is associated with a form element, then enqueue a custom element callback reaction with element, callback name "formAssociatedCallback", and « the associated form ».
- ~IF[ %要素 は`不能化されて$feいる ] ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `formDisabledCallback^l, « ~T » ) ◎ If element is disabled, then enqueue a custom element callback reaction with element, callback name "formDisabledCallback" and « true ».
- %要素 の`~custom要素~状態$el ~SET `custom^l ◎ Set element's custom element state to "custom".
`要素を昇格するよう試行する@ ときは、所与の ( 要素 %要素 ) に対し,次の手続きを走らす: ◎ To try to upgrade an element, given as input an element element, run the following steps:
- %定義 ~LET `~custom要素~定義を検索する$( %要素 の`~node文書$, %要素 の`名前空間$el, %要素 の`局所~名$el, %要素 の`~is0値$el ) ◎ Let definition be the result of looking up a custom element definition given element's node document, element's namespace, element's local name, and element's is value.
- ~IF[ %定義 ~NEQ ~NULL ] ⇒ `~custom要素~昇格~反応を~enqueueする$( %要素, %定義 ) ◎ If definition is not null, then enqueue a custom element upgrade reaction given element and definition.
4.13.6. ~custom要素~反応
`~custom要素$ %要素 は、 作者~codeを走らすことにより,一定の出来事に応答する能を備える: ◎ A custom element possesses the ability to respond to certain occurrences by running author code:
- %要素 が`昇格$されたときは、 `~custom要素~構築子$を引数なしで走らす。 ◎ When upgraded, its constructor is run, with no arguments.
- %要素 が`接続されたとき$は、 %要素 の `connectedCallback()^c が引数なしで~callされる。 ◎ When it becomes connected, its connectedCallback is called, with no arguments.
- %要素 が`切断されたとき$は、 %要素 の `disconnectedCallback()^c が引数なしで~callされる。 ◎ When it becomes disconnected, its disconnectedCallback is called, with no arguments.
- %要素 が他の文書に`受入された@~DOM4#concept-node-adopt$ときは、 %要素 の `adoptedCallback()^c が ( 旧-文書, 新-文書 ) を引数に~callされる。 ◎ When it is adopted into a new document, its adoptedCallback is called, given the old document and new document as arguments.
- %要素 のいずれかの属性が[ `変更された@~DOM4#concept-element-attributes-change$ / `付加された@~DOM4#concept-element-attributes-append$ / `除去された@~DOM4#concept-element-attributes-remove$ / `置換された@~DOM4#concept-element-attributes-replace$ ]ときは、 %要素 の `attributeChangedCallback()^c が当の属性の ( `局所~名$attr, 旧-`値$attr, 新-`値$attr, `名前空間$attr ) を引数に~callされる (属性が[ 付加された/除去された ]ときは、 属性の[ 旧-値/新-値 ]は ~NULL と見なされる)。 ◎ When any of its attributes are changed, appended, removed, or replaced, its attributeChangedCallback is called, given the attribute's local name, old value, new value, and namespace as arguments. (An attribute's old or new value is considered to be null when the attribute is added or removed, respectively.)
-
%要素 が`~formに所有され得る~custom要素$でもある場合: ◎ ↓
- %要素 の`~form所有者を設定し直す$ことにより, %要素 の`~form所有者$が変化したときは、 %要素 の `formAssociatedCallback()^c が ( 変化-後の~form所有者( ~NULL にもなり得る) ) を引数に~callされる。 ◎ When the user agent resets the form owner of a form-associated custom element and doing so changes the form owner, its formAssociatedCallback is called, given the new form owner (or null if no owner) as an argument.
- `~formを再設定する$ことにより, %要素 の`再設定~algo$が呼出されるときは、 %要素 の `formResetCallback()^c が~callされる。 ◎ When the form owner of a form-associated custom element is reset, its formResetCallback is called.
- %要素 が`不能化されて$feいるか否かが変化したときは、 %要素 の `formDisabledCallback()^c が ( 新たな状態 ) を引数に~callされる。 ◎ When the disabled state of a form-associated custom element is changed, its formDisabledCallback is called, given the new state as an argument.
- ~UAが[ 利用者に利するため/ `~naviの一部@~HTMLnav#restore-persisted-state$として ],`~formに所有され得る~custom要素$の値【`値@~HTMLforms#concept-fe-value$?】を更新したときは、 %要素 の `formStateRestoreCallback()^c が ( 新たな状態, 理由を指示する文字列[ `autocomplete^l / `restore^l ] ) を引数に~callされる。 ◎ When user agent updates a form-associated custom element's value on behalf of a user or as part of navigation, its formStateRestoreCallback is called, given the new state and a string indicating a reason, "autocomplete" or "restore", as arguments.
これらの反応は、 `~custom要素~反応@ と総称される。 ◎ We call these reactions collectively custom element reactions.
`~custom要素~反応$は、[ それを与える作者~codeが,他から~~干渉されると困る演算の途中で走らない ]よう,特別に~careされる下で呼出される。 それらの反応は、 実質的に “利用元~scriptに返る直前” まで遅延される。 このことは、次を意味する ⇒ ほとんどの目的においては,それらは同期的に実行するように現れるが、 いくつかの演算 (`~nodeを~cloneする$, `範囲$を操作するなど) が複雑に組成された事例では, 関連な~UA処理~段~すべてが完了するまで遅延された上で,~~一括して走らす。 ◎ The way in which custom element reactions are invoked is done with special care, to avoid running author code during the middle of delicate operations. Effectively, they are delayed until "just before returning to user script". This means that for most purposes they appear to execute synchronously, but in the case of complicated composite operations (like cloning, or range manipulation), they will instead be delayed until after all the relevant user agent processing steps have completed, and then run together as a batch.
加えて,これらの反応の精確な順序付けは、 以下に述べる[ ~queueたちが成す~stackに基づく,いくぶん複雑な~system ]を介して管理される。 この~systemの背後にある意図nは、 少なくとも[ 単独の`~custom要素$における局所的な文脈 ]の中では,[ 各`~custom要素~反応$は、 常に,それらを誘発した動作たちの順序と同じ順序で呼出される ]ことを保証することである。 (`~custom要素~反応$の~codeは,自前で【他の要素に対する】変異を遂行できるので、 複数の要素にわたる大域的な順序付けを保証することは,アリでない) ◎ Additionally, the precise ordering of these reactions is managed via a somewhat-complicated stack-of-queues system, described below. The intention behind this system is to guarantee that custom element reactions always are invoked in the same order as their triggering actions, at least within the local context of a single custom element. (Because custom element reaction code can perform its own mutations, it is not possible to give a global ordering guarantee across multiple elements.)
各 `生成元が類似な~window~agent$ %A には、 `~custom要素~反応~stack@ があり,初期~時は空とする。 この~stackを成す各~itemは、 `要素~queue@ であり,これらも初期~時は空とする。 また、 この~stackの一番上に積まれた`要素~queue$を,特に %A の `現在の要素~queue@ という。 `要素~queue$を成す各~itemは、 要素である (この~queueは,`昇格$用にも利用されるので、 各~要素は,この時点では必ずしも`~custom$elであるとは限らない)。 ◎ Each similar-origin window agent has a custom element reactions stack, which is initially empty. A similar-origin window agent's current element queue is the element queue at the top of its custom element reactions stack. Each item in the stack is an element queue, which is initially empty as well. Each item in an element queue is an element. (The elements are not necessarily custom yet, since this queue is used for upgrades as well.)
各`~custom要素~反応~stack$には、 `予備の要素~queue@ も結付けられる — それは、`要素~queue$であり,初期~時は空とする。 [ `CEReactions$xA 付きの~APIを通さずに, あるいは 構文解析器の`~tokenに対し要素を作成する$~algoを通して ]~DOMに影響するような演算の間、 要素は`予備の要素~queue$に~pushされる。 例えば、 `編集-可能$な要素の子孫や属性を改変するような,利用者により起動される編集~演算が挙げられる。 `予備の要素~queue$の処理-時における再入を防ぐため、 各`~custom要素~反応~stack$には, `予備の要素~queueは処理-中か@ も結付けられる — それは、真偽値であり,初期-時は ~F とする。 ◎ Each custom element reactions stack has an associated backup element queue, which is an initially-empty element queue. Elements are pushed onto the backup element queue during operations that affect the DOM without going through an API decorated with [CEReactions], or through the parser's create an element for the token algorithm. An example of this is a user-initiated editing operation which modifies the descendants or attributes of an editable element. To prevent reentrancy when processing the backup element queue, each custom element reactions stack also has a processing the backup element queue flag, initially unset.
各 要素には、 `~custom要素~反応~queue@ が結付けられ,初期~時は空とする。 `~custom要素~反応~queue$を成す各~itemは、 次の 2 種いずれかになる: ◎ All elements have an associated custom element reaction queue, initially empty. Each item in the custom element reaction queue is of one of two types:
- `昇格~反応@ ⇒ これは、 ~custom要素を`昇格$することになり,`~custom要素~定義$を包含する。 ◎ An upgrade reaction, which will upgrade the custom element and contains a custom element definition; or
- `~callback反応@ ⇒ これは、 ~lifecycle~callbackを~callすることになり,[ ~callback関数, その引数たちが成す~list ]を包含する。 ◎ A callback reaction, which will call a lifecycle callback, and contains a callback function as well as a list of arguments.
これらすべては、 次の図式に要約される: ◎ This is all summarized in the following schematic diagram:
`適切な要素~queueに~enqueueする@ ときは、所与の ( 要素 %要素 ) に対し,次の手続きを走らす: ◎ To enqueue an element on the appropriate element queue, given an element element, run the following steps:
- %反応~stack ~LET %要素 に`関連な~agent$の`~custom要素~反応~stack$ ◎ Let reactionsStack be element's relevant agent's custom element reactions stack.
-
~IF[ %反応~stack は空である ]: ◎ If reactionsStack is empty, then:
- %要素 を %反応~stack の`予備の要素~queue$に追加する ◎ Add element to reactionsStack's backup element queue.
- ~IF[ %反応~stack の`予備の要素~queueは処理-中か$ ~EQ ~T ] ⇒ ~RET ◎ If reactionsStack's processing the backup element queue flag is set, then return.
- %反応~stack の`予備の要素~queueは処理-中か$ ~SET ~T ◎ Set reactionsStack's processing the backup element queue flag.
-
`小taskを~queueする$( 次の手続き ) ◎ Queue a microtask to perform the following steps:
手続きは: ◎ ↑
- `~custom要素~反応たちを呼出す$( %反応~stack の`予備の要素~queue$ ) ◎ Invoke custom element reactions in reactionsStack's backup element queue.
- %反応~stack の`予備の要素~queueは処理-中か$ ~SET ~F ◎ Unset reactionsStack's processing the backup element queue flag.
- ~ELSE ⇒ %要素 を %要素 に`関連な~agent$の`現在の要素~queue$に追加する ◎ Otherwise, add element to element's relevant agent's current element queue.
`~custom要素~callback反応を~enqueueする@ ときは、所与の ( `~custom要素$ %要素, ~callback名 %~callback名, 引数~list %引数~list ) に対し,次の手続きを走らす: ◎ To enqueue a custom element callback reaction, given a custom element element, a callback name callbackName, and a list of arguments args, run the following steps:
- %定義 ~LET %要素 の`~custom要素~定義$el ◎ Let definition be element's custom element definition.
- %~callback ~LET %定義 の`~lifecycle~callback~map$cD[ %~callback名 ] ◎ Let callback be the value of the entry in definition's lifecycle callbacks with key callbackName.
- ~IF[ %~callback ~EQ ~NULL ] ⇒ ~RET ◎ If callback is null, then return.
-
~IF[ %~callback名 ~EQ `attributeChangedCallback^l ]: ◎ If callbackName is "attributeChangedCallback", then:
- ~Assert: %引数~list は空でない【この段は、この訳による補完】
- %属性~名 ~LET %引数~list[ 0 ] ◎ Let attributeName be the first element of args.
- ~IF[ %属性~名 ~NIN %定義 の`観測される属性~群$cD ] ⇒ ~RET ◎ If definition's observed attributes does not contain attributeName, then return.
- %要素 の`~custom要素~反応~queue$に次を追加する ⇒ ( ~callback関数, 引数~list ) として ( %~callback, %引数~list ) を伴う, 新たな`~callback反応$ ◎ Add a new callback reaction to element's custom element reaction queue, with callback function callback and arguments args.
- `適切な要素~queueに~enqueueする$( %要素 ) ◎ Enqueue an element on the appropriate element queue given element.
`~custom要素~昇格~反応を~enqueueする@ ときは、所与の ( 要素 %要素, `~custom要素~定義$ %定義 ) に対し,次の手続きを走らす: ◎ To enqueue a custom element upgrade reaction, given an element element and custom element definition definition, run the following steps:
- %要素 の`~custom要素~反応~queue$に次を追加する ⇒ `~custom要素~定義$として %定義 を伴う,新たな`昇格~反応$ ◎ Add a new upgrade reaction to element's custom element reaction queue, with custom element definition definition.
- `適切な要素~queueに~enqueueする$( %要素 ) ◎ Enqueue an element on the appropriate element queue given element.
`~custom要素~反応たちを呼出す@ ときは、所与の ( `要素~queue$ %~queue ) に対し,次の手続きを走らす: ◎ To invoke custom element reactions in an element queue queue, run the following steps:
-
~WHILE[ %~queue は`空$でない ]: ◎ While queue is not empty:
- %要素 ~LET %~queue から`~dequeueする$ ◎ Let element be the result of dequeuing from queue.
- %反応~queue ~LET %要素 の`~custom要素~反応~queue$ ◎ Let reactions be element's custom element reaction queue.
-
~WHILE[ %反応~queue は空でない ]: ◎ Repeat until reactions is empty:
- %反応~queue から最初の~itemを除去する ◎ Remove the first element of reactions, and\
- %反応 ~LET 前~段で除去した~item ◎ let reaction be that element.\ Switch on reaction's type:
-
~IF[ %反応 は`昇格~反応$である ] ⇒ `要素を昇格する$( %反応 の`~custom要素~定義$, %要素 ) ◎ • upgrade reaction •• Upgrade element using reaction's custom element definition.
例外 %e が投出されたときは、 ~catchして ⇒ `例外を報告する$( %e, %反応 の`~custom要素~定義$の`構築子$cDに対応している~JS~objが`属する~realm$の`大域~obj$rM ) ◎ •• If this throws an exception, catch it, and report it for reaction's custom element definition's constructor's corresponding JavaScript object's associated realm's global object.
- ~ELSE ( %反応 は`~callback反応$である) ⇒ `~callback関数を呼出す$( %反応 の~callback関数, %反応 の引数~list, `報告する^i, %要素 ) ◎ • callback reaction •• Invoke reaction's callback function with reaction's arguments and "report", and callback this value set to element.
`~custom要素~反応$が適切に誘発されることを確保するため、 この仕様は, `CEReactions@xA ~IDL`拡張d属性$を導入する。 それは、 `~custom要素~反応$を適切に追跡して呼出すため, 関連な~algoに追加的な手続きを補足することを指示する。 ◎ To ensure custom element reactions are triggered appropriately, we introduce the [CEReactions] IDL extended attribute. It indicates that the relevant algorithm is to be supplemented with additional steps in order to appropriately track and invoke custom element reactions.
`CEReactions$xA 拡張d属性は:
- 引数をとってはナラナイ。
- [ 演算, 属性, 設定子, 削除子 ]以外のものに現れてはナラナイ。
- 読専( `readonly^en )属性~上に現れてはナラナイ。
【 これら各種~IDL用語の参照先: `演算@~WEBIDL#idl-operations$, `属性@~WEBIDL#idl-attributes$, `設定子と削除子@~WEBIDL#idl-special-operations$, `読専@~WEBIDL#dfn-read-only$ 】
◎ The [CEReactions] extended attribute must take no arguments, and must not appear on anything other than an operation, attribute, setter, or deleter. Additionally, it must not appear on readonly attributes.`CEReactions$xA 拡張d属性で注釈された[ 演算, 属性, 設定子, 削除子 ]に対しては、 その[ 演算 / 設定子 / 削除子 / 属性の設定子 ]の記述に指定されている手続き %手続き に代えて,次を走らすモノトスル: ◎ Operations, attributes, setters, or deleters annotated with the [CEReactions] extended attribute must run the following steps in place of the ones specified in their description:
- コレに`関連な~agent$の`~custom要素~反応~stack$に新たな`要素~queue$を`~pushする$ ◎ Push a new element queue onto this object's relevant agent's custom element reactions stack.
- %例外 ~LET ε ◎ ↓
- %値 ~SET %手続き を走らせた結果 ⇒ 例外が投出されたときは、 ~catchして ⇒ %例外 ~SET その例外 ◎ Run the originally-specified steps for this construct, catching any exceptions. If the steps return a value, let value be the returned value. If they throw an exception, let exception be the thrown exception.
- %~queue ~LET コレに`関連な~agent$の`~custom要素~反応~stack$から`~popする$ ◎ Let queue be the result of popping from this object's relevant agent's custom element reactions stack.
- `~custom要素~反応たちを呼出す$( %~queue ) ◎ Invoke custom element reactions in queue.
- ~IF[ %例外 ~NEQ ε ] ⇒ ~THROW %例外 ◎ If an exception exception was thrown by the original steps, rethrow exception.
- ~RET %値 ◎ If a value value was returned from the original steps, return value.
注記: この拡張d属性の背後にある意図には、 微妙な所がある。 その目標を成遂げるためには、 代わりに,次を記しておく仕方もあるが…: ◎ The intent behind this extended attribute is somewhat subtle. One way of accomplishing its goals would be to say that\
- ~platformの どの[ 演算, 属性, 設定子, 削除子 ]にも,上述の手続きを挿入しなければならない。 ◎ every operation, attribute, setter, and deleter on the platform must have these steps inserted,\
- 実装者には、 不必要な事例については最適化して外すことも許容される (そこでは、 `~custom要素~反応$を生じさせるような~DOM変異は,アリでない)。 ◎ and to allow implementers to optimize away unnecessary cases (where no DOM mutation is possible that could cause custom element reactions to occur).
…が,このような不精確な~~指定では、 実施において相互運用可能でない`~custom要素~反応$の実装へ至らせ得る — ある実装は、 一部の事例で,この手続きを呼出すのを忘れるかもしれない。 相互運用可能な挙動を確保する代わりの仕方として、 次の~approachにより決着された ⇒ 関連な どの~IDL構成子にも,この拡張d属性で明示的に注釈して、 この手続きが必要yな事例~すべてを,実装者が容易に見分けられるようする。 ◎ However, in practice this imprecision could lead to non-interoperable implementations of custom element reactions, as some implementations might forget to invoke these steps in some cases. Instead, we settled on the approach of explicitly annotating all relevant IDL constructs, as a way of ensuring interoperable behavior and helping implementations easily pinpoint all cases where these steps are necessary.
~UAにより導入される標準でない~APIのうち,~DOMを改変し得るもの — 例えば、何らかの属性や子~要素を改変するもの — は、 その結果[ `~custom要素~callback反応を~enqueueする$ / `~custom要素~昇格~反応を~enqueueする$ ]ことになるならば, `CEReactions$xA 拡張d属性で注釈されなければナラナイ。 ◎ Any nonstandard APIs introduced by the user agent that could modify the DOM in such a way as to cause enqueuing a custom element callback reaction or enqueuing a custom element upgrade reaction, for example by modifying any attributes or child elements, must also be decorated with the [CEReactions] attribute.
注記: これを書いている時点では、 次に挙げる[ 標準でない, または標準~化されていない ]~APIが,これに該当するものとして知られている: ◎ As of the time of this writing, the following nonstandard or not-yet-standardized APIs are known to fall into this category:
- `HTMLInputElement$I の[ `webkitdirectory^m, `incremental^m ]~IDL属性 ◎ HTMLInputElement's webkitdirectory and incremental IDL attributes
- `HTMLLinkElement$I の `scope^m ~IDL属性 ◎ HTMLLinkElement's scope IDL attribute
4.13.7. 要素の内部特能
一定の能力は、 ~custom要素の消費者ではなく,その作者から可用になるものと意味される。 それらは、 `attachInternals()$m ~methodが返す `ElementInternals$I の~instanceにより供される。 `ElementInternals$I の各種[ ~prop/~method ]は、[ ~UAがすべての要素に供する内部~特能 ]に対する制御を許容する。 ◎ Certain capabilities are meant to be available to a custom element author, but not to a custom element consumer. These are provided by the element.attachInternals() method, which returns an instance of ElementInternals. The properties and methods of ElementInternals allow control over internal features which the user agent provides to all elements.
- %element.`attachInternals()$m
- `~custom要素$ %element を~targetにしている `ElementInternals$I ~objを返す。 次のいずれかに該当する場合、 例外を投出する ⇒# %element は`~custom要素$でない/ 要素~定義を成す一部として `internals^l 特能は不能化されている/ 同じ要素~上で重ねて~callされたとき ◎ Returns an ElementInternals object targeting the custom element element. Throws an exception if element is not a custom element, if the "internals" feature was disabled as part of the element definition, or if it is called twice on the same element.
各 `HTMLElement$I には、 それに `付された内部特能@ がある — それは[ ~NULL / `ElementInternals$I ~obj ]であり, 初期~時は ~NULL とする。 ◎ Each HTMLElement has an attached internals (null or an ElementInternals object), initially null.
`attachInternals()@m ~method手続きは: ◎ The attachInternals() method steps are:
- ~IF[ コレの`~is0値$el ~NEQ ~NULL ] ⇒ ~THROW `NotSupportedError$E ◎ If this's is value is not null, then throw a "NotSupportedError" DOMException.
- %定義 ~LET `~custom要素~定義を検索する$( コレの`~node文書$, コレの`名前空間$el, コレの`局所~名$el, ~NULL ) ◎ Let definition be the result of looking up a custom element definition given this's node document, its namespace, its local name, and null as the is value.
- ~IF[ %定義 ~EQ ~NULL ] ⇒ ~THROW `NotSupportedError$E ◎ If definition is null, then throw an "NotSupportedError" DOMException.
- ~IF[ %定義 の`内部特能を不能化するか$cD ~EQ ~T ] ⇒ ~THROW `NotSupportedError$E ◎ If definition's disable internals is true, then throw a "NotSupportedError" DOMException.
- ~IF[ コレに`付された内部特能$ ~NEQ ~NULL ] ⇒ ~THROW `NotSupportedError$E ◎ If this's attached internals is non-null, then throw an "NotSupportedError" DOMException.
- ~IF[ コレの`~custom要素~状態$el ~NIN { `precustomized^l, `custom^l } ] ⇒ ~THROW `NotSupportedError$E ◎ If this's custom element state is not "precustomized" or "custom", then throw a "NotSupportedError" DOMException.
- コレに`付された内部特能$ ~SET 新たな `ElementInternals$I ~instance — その ⇒# `~target要素$iN ~SET コレ ◎ Set this's attached internals to a new ElementInternals instance whose target element is this.
- ~RET コレに`付された内部特能$ ◎ Return this's attached internals.
4.13.7.1. `ElementInternals^I ~interface
`ElementInternals$I ~interface用の~IDLは、 以下の各節にて定義される様々な演算, 属性を伴う: ◎ The IDL for the ElementInternals interface is as follows, with the various operations and attributes defined in the following sections:
[Exposed=Window] interface `ElementInternals@I { /* `§ ~shadow根への~access@#shadow-root-access$ ◎ Shadow root access */ readonly attribute `ShadowRoot$I? `shadowRoot$eI; /* `§ ~formに所有され得る~custom要素@#form-associated-custom-elements$ ◎ Form-associated custom elements */ undefined `setFormValue$eI( (`File$I or `USVString$ or `FormData$I)? %value, optional (`File$I or `USVString$ or `FormData$I)? %state ); readonly attribute `HTMLFormElement$I? `form$eI; undefined `setValidity$eI( optional `ValidityStateFlags$I %flags = {}, optional DOMString %message, optional `HTMLElement$I %anchor ); readonly attribute boolean `willValidate$eI; readonly attribute `ValidityState$I `validity$eI; readonly attribute DOMString `validationMessage$eI; boolean `checkValidity$eI(); boolean `reportValidity$eI(); /* `~custom状態~疑似類@#custom-state-pseudo-class$ ◎ Custom state pseudo-class */ [SameObject] readonly attribute `CustomStateSet$I `states$eI; readonly attribute `NodeList$I `labels$eI; }; /* `§ ~accessibility意味論@#accessibility-semantics$ ◎ Accessibility semantics */ `ElementInternals$I includes `ARIAMixin$I; dictionary `ValidityStateFlags@I { boolean valueMissing = false; boolean typeMismatch = false; boolean patternMismatch = false; boolean tooLong = false; boolean tooShort = false; boolean rangeUnderflow = false; boolean rangeOverflow = false; boolean stepMismatch = false; boolean badInput = false; boolean customError = false; };
各 `ElementInternals$I は、 ある`~custom要素$を指す `~target要素@iN を有する。 ◎ Each ElementInternals has a target element, which is a custom element.
4.13.7.2. ~shadow根への~access
- %internals.`shadowRoot$eI
- %internals の`~target要素$iNは[ `~shadow~host$であるならば,それ用の `ShadowRoot$I / ~ELSE_ ~NULL ]を返す。 ◎ Returns the ShadowRoot for internals's target element, if the target element is a shadow host, or null otherwise.
`shadowRoot@eI 取得子~手続きは: ◎ The shadowRoot getter steps are:
- %~target ~LET コレの`~target要素$iN ◎ Let target be this's target element.
- ~IF[ %~target は`~shadow~host$でない ] ⇒ ~RET ~NULL ◎ If target is not a shadow host, then return null.
- %~shadow ~LET %~target の`~shadow根$el ◎ Let shadow be target's shadow root.
- ~IF[ %~shadow の`要素の内部特能から可用か$ ~EQ ~F ] ⇒ ~RET ~NULL ◎ If shadow's available to element internals is false, then return null.
- ~RET %~shadow ◎ Return shadow.
4.13.7.3. ~formに所有され得る~custom要素
- %internals.`setFormValue(value)$eI
- %internals の`~target要素$iNの[ `状態$cF, `提出~値$cF ]とも %value に設定する。 ◎ Sets both the state and submission value of internals's target element to value.
- %value ~EQ ~NULL の場合、 要素は~form提出に関与しなくなる。 ◎ If value is null, the element won't participate in form submission.
- %internals.`setFormValue(value, state)$eI
- %internals の`~target要素$iNの[ `提出~値$cF/`状態$cF ]を[ %value / %state ]に設定する。 ◎ Sets the submission value of internals's target element to value, and its state to state.
- %value ~EQ ~NULL の場合、 要素は~form提出に関与しなくなる。 ◎ If value is null, the element won't participate in form submission.
- %internals.`form$eI
- %internals の`~target要素$iNの`~form所有者$を返す。 ◎ Returns the form owner of internals's target element.
- %internals.`setValidity(flags, message [, anchor ])$eI
- [ %internals の`~target要素$iNは、 %flags 引数が指示する拘束に関して難ありである ]ものと~markした上で、 要素の検証~messageを %message に設定する。 ◎ Marks internals's target element as suffering from the constraints indicated by the flags argument, and sets the element's validation message to message.\
- %anchor も指定された場合、 ~UAは,[ `~form所有者$は対話的に検証された / `reportValidity()$eI が~callされた ]とき[ %internals の`~target要素$iNの拘束についての問題を指示する ]ために,それを利用するかもしれない。 ◎ If anchor is specified, the user agent might use it to indicate problems with the constraints of internals's target element when the form owner is validated interactively or reportValidity() is called.
- %internals.`setValidity({})$eI
- [ %internals の`~target要素$iNは、 `自身の拘束を満たして$いる ]ものと~markする。 ◎ Marks internals's target element as satisfying its constraints.
- %internals.`willValidate$eI
- ~formが提出されるとき,%internals の`~target要素$iNは[ 検証されることになるならば ~T / ~ELSE_ ~F ]を返す。 ◎ Returns true if internals's target element will be validated when the form is submitted; false otherwise.
- %internals.`validity$eI
- %internals の`~target要素$iN用の `ValidityState$I ~objを返す。 ◎ Returns the ValidityState object for internals's target element.
- %internals.`validationMessage$eI
- [ %internals の`~target要素$iNの妥当性が検査されたとき,利用者に示される ]ことになる,~error~messageを返す。 ◎ Returns the error message that would be shown to the user if internals's target element was to be checked for validity.
- %valid = %internals.`checkValidity()$eI
- %internals の`~target要素$iNに妥当性の問題は[ ないならば ~T / あるならば ~F ]を返す。 ~F を返す場合、 要素に向けて `invalid$et ~eventを発火する。 ◎ Returns true if internals's target element has no validity problems; false otherwise. Fires an invalid event at the element in the latter case.
- %valid = %internals.`reportValidity()$eI
- %internals の`~target要素$iNに妥当性の問題は[ ないならば ~T / あるならば ~F ]を返す。 ~F を返す場合、 要素に向けて `invalid$et ~eventを発火することに加え, (~eventが取消されなければ)利用者に問題を報告する。 ◎ Returns true if internals's target element has no validity problems; otherwise, returns false, fires an invalid event at the element, and (if the event isn't canceled) reports the problem to the user.
- %internals.`labels$eI
- [ %internals の`~target要素$iNを`~label先~control$とする `label$e 要素 ]すべてからなる `NodeList$I を返す。 ◎ Returns a NodeList of all the label elements that internals's target element is associated with.
各`~formに所有され得る~custom要素$は、 次に挙げるものを有する: ◎ ↓
- `提出~値@cF ⇒ ~form提出~用に 1 個~以上の`~entry$fDを供するために利用される。 次に挙げる いずれかの値をとり,初期~時は ~NULL とする ⇒# ~NULL / 文字列 / `File$I ~obj / `~entry~list$【!`~entry$fDが成す`~list$】 ◎ Each form-associated custom element has submission value. It is used to provide one or more entries on form submission. The initial value of submission value is null, and submission value can be null, a string, a File, or a list of entries.
- `状態@cF ⇒ この要素~用に,~UAが利用者の入力を復旧できる情報。 `提出~値$cFと同じ範囲の値をとり,初期~時は ~NULL とする。 ◎ Each form-associated custom element has state. It is information with which the user agent can restore a user's input for the element. The initial value of state is null, and state can be null, a string, a File, or a list of entries.
~custom要素の作者は、 `setFormValue()$eI ~methodを利用して,要素の[ `提出~値$cF, `状態$cF ]を設定できる — それらは~UAに通信される。 ◎ The setFormValue() method is used by the custom element author to set the element's submission value and state, thus communicating these to the user agent.
`~formに所有され得る~custom要素$ %要素 に対しては,~UAは: ◎ ↓
- %要素 の`状態$cFを復旧することが良案になると予見するときには — 例えば,`~naviの後@~HTMLnav#restore-persisted-state$や再起動~後に — 次をしてもヨイ ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `formStateRestoreCallback^l, « 復旧されることになる状態, `restore^l » ) ◎ When the user agent believes it is a good idea to restore a form-associated custom element's state, for example after navigation or restarting the user agent, they may enqueue a custom element callback reaction with that element, callback name "formStateRestoreCallback", and « the state to be restored, "restore" ».
- ~formを埋めるための支援-特能を備えていて,当の特能が呼出されたときは、 次をしてもヨイ ⇒ `~custom要素~callback反応を~enqueueする$( %要素, `formStateRestoreCallback^l, « [ 状態~値の履歴, 何らかの経験則 ]により決定される状態~値, `autocomplete^l » ) ◎ If the user agent has a form-filling assist feature, then when the feature is invoked, it may enqueue a custom element callback reaction with a form-associated custom element, callback name "formStateRestoreCallback", and « the state value determined by history of state value and some heuristics, "autocomplete" ».
一般に、 `状態$cFは[ 利用者により指定された情報 ]であり,`提出~値$cFは[ ~serverへの提出~用に相応しくなるよう,正準-化や無毒化を施した後の値 ]である。 具体的には: ◎ In general, the state is information specified by a user, and the submission value is a value after canonicalization or sanitization, suitable for submission to the server. The following examples makes this concrete:
`~formに所有され得る~custom要素$が在って,日付を指定するよう利用者に依頼するとする。 利用者は "3/15/2019" と指定したが,~controlは `2019-03-15^l を~serverへ提出したいと望む場合、 要素の ⇒# `状態$cFは "3/15/2019" になる/ `提出~値$cFは `2019-03-15^l になる ◎ Suppose that we have a form-associated custom element which asks a user to specify a date. The user specifies "3/15/2019", but the control wishes to submit "2019-03-15" to the server. "3/15/2019" would be a state of the element, and "2019-03-15" would be a submission value.
既存の[ `Checkbox$st 状態にある `input$e 要素 ]の挙動を模倣する~custom要素を開発しているとする。 要素の:
- `提出~値$cFは、 次のいずれかになる ⇒# 要素の `value^a 内容~属性の値/ 文字列 `on^l
- `状態$cFは、 次のいずれかになる ⇒# `checked^l / `unchecked^l / `checked/indeterminate^l / `unchecked/indeterminate^l
`setFormValue(value, state)@eI ~method手続きは: ◎ The setFormValue(value, state) method steps are:
- %要素 ~LET コレの`~target要素$iN ◎ Let element be this's target element.
- ~IF[ %要素 は`~formに所有され得る~custom要素$でない ] ⇒ ~THROW `NotSupportedError$E ◎ If element is not a form-associated custom element, then throw a "NotSupportedError" DOMException.
- ~IF[ %value は `FormData$I ~objである ] ⇒ %value ~SET %value の`~entry~list$fDを`~cloneする$ ◎ ↓
- %要素 の`提出~値$cF ~SET %value ◎ Set target element's submission value to value if value is not a FormData object, or to a clone of value's entry list otherwise.
- ~IF[ %state ~EQ ε ] ⇒ %state ~SET %要素 の`提出~値$cF ◎ If the state argument of the function is omitted, set element's state to its submission value.
- ~ELIF[ %state は `FormData$I ~objである ] ⇒ %state ~SET %state の`~entry~list$fDを`~cloneする$ ◎ Otherwise, if state is a FormData object, set element's state to a clone of state's entry list.
- %要素 の`状態$cF ~SET %state ◎ Otherwise, set element's state to state.
各`~formに所有され得る~custom要素$は、 次に挙げるものを有する: ◎ ↓
-
`妥当性~flag群@cF ⇒ `ValidityStateFlags$I と同じ構造の~map。 すなわち、 その各~memberと同じ名前の~keyたちを伴う。 各~keyに対応する値は、 どれも初期~時は ~F とする†。 ◎ Each form-associated custom element has validity flags named valueMissing, typeMismatch, patternMismatch, tooLong, tooShort, rangeUnderflow, rangeOverflow, stepMismatch, and customError. They are false initially.
【 原文では,これら各~memberと同じ名前の~flagを列挙している (加えて `badInput^m も抜けている)が、 総称し易くするため,この訳ではこの用語に代えることにする。 】【† 値 ~T は、 (各~keyの名前が示唆するとおり,) 当の~keyに対応する`妥当性~状態$に “難あり” を意味する。 】
- `検証~message@cF ⇒ 文字列 — 初期~時は空~文字列とする。 ◎ Each form-associated custom element has a validation message string. It is the empty string initially.
- `検証~anchor@cF ⇒ 要素/ ~NULL — 初期~時は ~NULL とする。 【拘束を`対話的に検証する$ときに利用される。】 ◎ Each form-associated custom element has a validation anchor element. It is null initially.
`setValidity(flags, message, anchor)@eI ~method手続きは: ◎ The setValidity(flags, message, anchor) method steps are:
- %要素 ~LET コレの`~target要素$iN ◎ Let element be this's target element.
- ~IF[ %要素 は`~formに所有され得る~custom要素$でない ] ⇒ ~THROW `NotSupportedError$E ◎ If element is not a form-associated custom element, then throw a "NotSupportedError" DOMException.
- %妥当か ~LET ~T ◎ ↓
- %flags を成す ~EACH( %flag → %値 ) に対し ⇒ ~IF[ %値 ~EQ ~T ] ⇒# %妥当か ~SET ~F; ~BREAK ◎ ↓
- ~IF[ %message ~EQ ε ] ⇒ %message ~SET 空~文字列 ◎ ↓
- ~IF[ %message ~EQ 空~文字列 ]~AND[ %妥当か ~EQ ~F ] ⇒ ~THROW `TypeError$E ◎ If flags contains one or more true values and message is not given or is the empty string, then throw a TypeError.
- %flags を成す ~EACH( %flag → %値 ) に対し ⇒ %要素 の`妥当性~flag群$cF[ %flag ] ~SET %値 ◎ For each entry flag → value of flags, set element's validity flag with the name flag to value.
- %要素 の`検証~message$cF ~SET %妥当か に応じて ⇒# ~T ならば 空~文字列 / ~F ならば %message ◎ Set element's validation message to the empty string if message is not given or all of element's validity flags are false, or to message otherwise.
- %要素 の`~custom妥当性~error~message$ ~SET %要素 の`妥当性~flag群$cF[ `customError^l ] に応じて ⇒# ~T ならば %要素 の`検証~message$cF / ~F ならば 空~文字列 ◎ If element's customError validity flag is true, then set element's custom validity error message to element's validation message. Otherwise, set element's custom validity error message to the empty string.
- ~IF[ %anchor ~EQ ε ] ⇒ %anchor ~SET ~NULL ◎ Set element's validation anchor to null if anchor is not given.\
- ~ELIF[ %anchor は %要素 の`~shadowも含めた子孫$でない ] ⇒ ~THROW `NotFoundError$E ◎ Otherwise, if anchor is not a shadow-including descendant of element, then throw a "NotFoundError" DOMException.\
- %要素 の`検証~anchor$cF ~SET %anchor ◎ Otherwise, set element's validation anchor to anchor.
`validationMessage@eI 取得子~手続きは: ◎ The validationMessage getter steps are:
- %要素 ~LET コレの`~target要素$iN ◎ Let element be this's target element.
- ~IF[ %要素 は`~formに所有され得る~custom要素$でない ] ⇒ ~THROW `NotSupportedError$E ◎ If element is not a form-associated custom element, then throw a "NotSupportedError" DOMException.
- ~RET %要素 の`検証~message$cF ◎ Return element's validation message.
`~formに所有され得る~custom要素$用の `~entry構築~algo@cF は、所与の ( 要素 %要素, `~entry~list$ %~entry~list ) に対し,次の手続きを走らす: ◎ The entry construction algorithm for a form-associated custom element, given an element element and an entry list entry list, consists of the following steps:
- %提出~値 ~LET %要素 の`提出~値$cF ◎ ↓
-
~IF[ %提出~値 は`~entry~list$【!`~entry$fDが成す`~list$】である ] ⇒# %~entry~list を %提出~値 で`拡張する$; ~RET ◎ If element's submission value is a list of entries, then append each item of element's submission value to entry list, and return.
この事例では、 ~UAは `name$a 内容~属性の値を~~無視する。 各`~entry$fDの`名$fDを裁定するのは、 `~formに所有され得る~custom要素$の実装が担当する。 名は、 `name$a 属性の値とは無関係な文字列にもなり得る。 ◎ In this case, user agent does not refer to the name content attribute value. An implementation of form-associated custom element is responsible to decide names of entries. They can be the name content attribute value, they can be strings based on the name content attribute value, or they can be unrelated to the name content attribute.
- %名 ~LET [ %要素 は `name$a 属性を有するならば その値 / ~ELSE_ 空~文字列 ] ◎ ↓
- ~IF[ %名 ~EQ 空~文字列 ] ⇒ ~RET ◎ If the element does not have a name attribute specified, or its name attribute's value is the empty string, then return.
- ~IF[ %提出~値 ~NEQ ~NULL ] ⇒ %~entry~list に次の結果を`付加する$ ⇒ `~entryを作成する$( %名, %提出~値 ) ◎ If the element's submission value is not null, create an entry with the name attribute value and the submission value, and append it to entry list.
4.13.7.4. ~accessibility意味論
- %internals.`role^eI [ = %value ]
- %internals の`~target要素$iN用の既定の~ARIA~roleを[ 設定する/検索取得する ] — それは、 ~page作者が `role$a 属性を利用して上書きしない限り, 利用されることになる。 ◎ Sets or retrieves the default ARIA role for internals's target element, which will be used unless the page author overrides it using the role attribute.
- %internals.`aria*^eI [ = %value ]
- %internals の`~target要素$iN用の 各種~ARIA[ 状態/~prop ]の既定の値を[ 設定する/検索取得する ](順不同) — それは、 各種 `aria-*$a 属性を利用して上書きしない限り, 利用されることになる。 ◎ Sets or retrieves various default ARIA states or property values for internals's target element, which will be used unless the page author overrides them using the aria-* attributes.
各`~custom要素$は、 `内部~内容~属性~map@ を有する — それは、 `~map$であり,初期~時は空とする。 これが ~platform~accessibility~APIにどう影響iするかの情報は、 `§ ~ARIA, および~platform~accessibility~APIに関係する要件@~HTMLdom#wai-aria$ を見よ。 ◎ Each custom element has an internal content attribute map, which is a map, initially empty. See the Requirements related to ARIA and to platform accessibility APIs section for information on how this impacts platform accessibility APIs.
4.13.7.5. ~custom状態~疑似類
- %internals.`states$eI.add(%value)
- 文字列 %value を当の要素の`状態~集合$に追加する — それは、 `state()$ps 疑似類を通して公開されることになる。 ◎ Adds the string value to the element's states set to be exposed as a pseudo-class.
- %internals.`states$eI.has(%value)
- %value は当の要素の`状態~集合$内に[ 在るならば ~T / 無いならば ~F ]を返す。 ◎ Returns true if value is in the element's states set, otherwise false.
- %internals.`states$eI.delete(%value)
- %value は当の要素の`状態~集合$内に在るならば、 それを集合から除去した上で, ~T を返す。 他の場合は ~F を返す。 ◎ If the element's states set has value, then it will be removed and true will be returned. Otherwise, false will be returned.
- %internals.`states$eI.clear()
- 当の要素の`状態~集合$からすべての値を除去する。 ◎ Removes all values from the element's states set.
- for (const %stateName of %internals.`states$eI)
- for (const %stateName of %internals.`states$eI.entries())
- for (const %stateName of %internals.`states$eI.keys())
- for (const %stateName of %internals.`states$eI.values())
- 当の要素の`状態~集合$を成すすべての値を反復する。 ◎ Iterates over all values in the element's states set.
- %internals.`states$eI.forEach(%callback)
- 当の要素の`状態~集合$を成すすべての値を[ 各~値に対し %callback を一回~callする ]ことにより反復する。 ◎ Iterates over all values in the element's states set by calling callback once for each value.
- %internals.`states$eI.size
- 当の要素の`状態~集合$を成す値の個数を返す。 ◎ Returns the number of values in the element's states set.
各`~custom要素$は `状態~集合@ を有する — それは、 ある `CustomStateSet$I であり,初期~時は空とする。 ◎ Each custom element has a states set, which is a CustomStateSet, initially empty.
[Exposed=Window] interface `CustomStateSet@I { setlike<DOMString>; };
`状態~集合$が公開できるものは、 文字列~値の有無により表現される真偽-状態である。 作者は、 3 種の値をとり得る状態を公開するよう求めるなら, 3 個の排他的な真偽-状態に変換できる。 例えば, `readyState^c と呼ばれる状態が値[ `loading^l, `interactive^l, `complete^l ]をとり得るなら、 3 個の排他的な真偽-状態[ `loading^l, `interactive^l, `complete^l ]に対応付けれる: ◎ The states set can expose boolean states represented by existence/non-existence of string values. If an author wants to expose a state which can have three values, it can be converted to three exclusive boolean states. For example, a state called readyState with "loading", "interactive", and "complete" values can be mapped to three exclusive boolean states, "loading", "interactive", and "complete":
/*
`readyState^c を `complete^l に変更する:
◎
Change the readyState from anything to "complete".
*/
this._readyState = "complete";
this._internals.states.delete("loading");
this._internals.states.delete("interactive");
this._internals.states.add("complete");