ã¦ã§ãã³ã³ãã¼ãã³ãã®ä¸»ãªç¹å¾´ã®ã²ã¨ã¤ã¯ãã«ã¹ã¿ã è¦ç´ ã使ã§ãããã¨ã§ããã¤ã¾ããã¦ã§ãéçºè ã«ãã£ã¦åä½ãå®ç¾©ããããã©ã¦ã¶ã¼ã§å©ç¨å¯è½ãªè¦ç´ ã»ãããæ¡å¼µãã HTML è¦ç´ ã§ãã
ãã®è¨äºã§ã¯ãã«ã¹ã¿ã è¦ç´ ã«ã¤ãã¦ç´¹ä»ããããã¤ãã®ä¾ã説æãã¾ãã
ã«ã¹ã¿ã è¦ç´ ã®ç¨®é¡ã«ã¹ã¿ã è¦ç´ ã«ã¯ 2 ã¤ã®ç¨®é¡ãããã¾ãã
ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ (Customized built-in element) ã¯ãæ¨æº HTML è¦ç´ ãä¾ãã° HTMLImageElement
ã HTMLParagraphElement
ãç¶æ¿ãã¾ãããããã®å®è£
ã«ãããæ¨æºè¦ç´ ã®ç¹å®ã®ã¤ã³ã¹ã¿ã³ã¹ã®åä½ãæ¡å¼µããã¾ãã
ã¡ã¢: ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ ã®å®è£
ã«é¢ããæ³¨æäºé
ã«ã¤ãã¦ã¯ãis
屿§ã®ãªãã¡ã¬ã³ã¹ãåç
§ãã¦ãã ããã
èªå¾åã«ã¹ã¿ã è¦ç´ (Autonomous custom element) 㯠HTML è¦ç´ ã®åºåºã¯ã©ã¹ã§ãã HTMLElement
ãç¶æ¿ãã¾ããä¸ããåä½ãå®è£
ããå¿
è¦ãããã¾ãã
ã«ã¹ã¿ã è¦ç´ ã¯ãHTMLElement
ãæ¡å¼µããã¯ã©ã¹ï¼èªå¾åè¦ç´ ã®å ´åï¼ã¾ãã¯ã«ã¹ã¿ãã¤ãºããã¤ã³ã¿ã¼ãã§ã¤ã¹ï¼ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ ã®å ´åï¼ã¨ãã¦å®è£
ããã¾ãã
以ä¸ã¯ãæå°éã®ã«ã¹ã¿ã è¦ç´ ã§ã<p>
è¦ç´ ãã«ã¹ã¿ãã¤ãºããå®è£
ä¾ã§ãã
class WordCount extends HTMLParagraphElement {
constructor() {
super();
}
// è¦ç´ ã®æ©è½ãããã«æ¸ã
}
æå°éã®èªå¾åã«ã¹ã¿ã è¦ç´ ã®å®è£ ã¯æ¬¡ã®ã¨ããã§ãã
class PopupInfo extends HTMLElement {
constructor() {
super();
}
// è¦ç´ ã®æ©è½ãããã«æ¸ã
}
ã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ãåæç¶æ ãæ¢å®å¤ã®è¨å®ãã¤ãã³ããªã¹ãã¼ã®ç»é²ãã·ã£ãã¦ã«ã¼ãã使ãããã¨ãªã©ãå¯è½ã§ãããã®æç¹ã§ã¯ãè¦ç´ ã®å±æ§ãåè¦ç´ ãæ¤æ»ããããæ°ãã屿§ãåè¦ç´ ã追å ãããããªãã§ãã ãããè¦ä»¶ã®ãã¹ã¦ã«ã¤ãã¦ã¯ãRequirements for custom element constructors and reactions ãåç §ãã¦ãã ããã
ã«ã¹ã¿ã è¦ç´ ã®ã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ã«ã¹ã¿ã è¦ç´ ãç»é²ãããã¨ããã¼ã¸ã®ã³ã¼ããã«ã¹ã¿ã è¦ç´ ã¨ç¹å®ã®æ¹æ³ã§ããåããè¡ãéã«ããã©ã¦ã¶ã¼ããã®ã¯ã©ã¹ã®ç¹å®ã®ã¡ã½ãããå¼ã³åºãã¾ãã 仿§æ¸ã§ã¯ãããã®ã¡ã½ããã®å®è£ ããã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ãã¨å¼ãã§ãã¾ããããããã®ã¡ã½ãããæä¾ãããã¨ã§ããããã®ã¤ãã³ãã«å¿çãã¦ã³ã¼ããå®è¡ãããã¨ãã§ãã¾ãã
ã«ã¹ã¿ã è¦ç´ ã®ã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ã«ã¯ã以ä¸ã®ãã®ãå«ã¾ãã¾ãã
connectedCallback()
: è¦ç´ ãææ¸ã«è¿½å ããããã³ã«å¼ã³åºããã¾ãã仿§ã§ã¯ãéçºè
ã¯å¯è½ãªéããã«ã¹ã¿ã è¦ç´ ã®è¨å®ãã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ãªãããã®ã³ã¼ã«ããã¯ã§å®è£
ãããã¨ãæ¨å¥¨ãã¦ãã¾ããdisconnectedCallback()
: è¦ç´ ãææ¸ããåé¤ããããã³ã«å¼ã³åºããã¾ããadoptedCallback()
: è¦ç´ ãæ°ããææ¸ã«ç§»åããããã³ã«å¼ã³åºããã¾ããattributeChangedCallback()
: 屿§ã夿´ã追å ãåé¤ãç½®æãããã¨ãã«å¼ã³åºããã¾ãããã®ã³ã¼ã«ããã¯ã®è©³ç´°ã«ã¤ãã¦ã¯ã屿§ã®å¤æ´ã¸ã®å¿çãåç
§ãã¦ãã ããããããã®ã©ã¤ããµã¤ã¯ã«ã¤ãã³ããè¨é²ããæå°éã®ã«ã¹ã¿ã è¦ç´ ã¯æ¬¡ã®ã¨ããã§ãã
// è¦ç´ ã®ããã®ã¯ã©ã¹ã使
class MyCustomElement extends HTMLElement {
static observedAttributes = ["color", "size"];
constructor() {
// ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ã常㫠super ãæåã«å¼ã³åºã
super();
}
connectedCallback() {
console.log("ã«ã¹ã¿ã è¦ç´ ããã¼ã¸ã«è¿½å ããã¾ããã");
}
disconnectedCallback() {
console.log("ã«ã¹ã¿ã è¦ç´ ããã¼ã¸ããé¤å»ããã¾ããã");
}
adoptedCallback() {
console.log("ã«ã¹ã¿ã è¦ç´ ãæ°ãããã¼ã¸ã¸ç§»åããã¾ããã");
}
attributeChangedCallback(name, oldValue, newValue) {
console.log(`屿§ ${name} ã夿´ããã¾ããã`);
}
}
customElements.define("my-custom-element", MyCustomElement);
ã«ã¹ã¿ã è¦ç´ ã®ç»é²
ã«ã¹ã¿ã è¦ç´ ããã¼ã¸ã§å©ç¨ã§ããããã«ããã«ã¯ãWindow.customElements
ã® define()
ã¡ã½ãããå¼ã³åºãã¾ãã
define()
ã¡ã½ããã¯ã以ä¸ã®å¼æ°ãåãã¾ãã
name
è¦ç´ ã®ååãããã¯å°æåã§å§ã¾ãããã¤ãã³ãå«ã¿ã仿§æ¸ã® definition of a valid name ã«è¨è¼ããã¦ãããã®ä»ã®ç¹å®ã®ã«ã¼ã«ãæºããå¿ è¦ãããã¾ãã
constructor
ã«ã¹ã¿ã è¦ç´ ã®ã³ã³ã¹ãã©ã¯ã¿ã¼é¢æ°ã
options
ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ ã®ã¿ã«å«ã¾ããããã¯åä¸ã®ãããã㣠extends
ãå«ããªãã¸ã§ã¯ãã§ããããã¯ãæ¡å¼µããçµã¿è¾¼ã¿è¦ç´ ã®ååãæå®ããæååã§ãã
ä¾ãã°ããã®ã³ã¼ãã¯ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ ã§ãã WordCount
ãç»é²ãã¾ãã
customElements.define("word-count", WordCount, { extends: "p" });
ãã®ã³ã¼ãã¯ãPopupInfo
ã¨ããèªå¾åã«ã¹ã¿ã è¦ç´ ãç»é²ãã¾ãã
customElements.define("popup-info", PopupInfo);
ã«ã¹ã¿ã è¦ç´ ã®ä½¿ç¨
ã«ã¹ã¿ã è¦ç´ ãå®ç¾©ãç»é²ããã¨ãã³ã¼ãã§ä½¿ç¨ã§ããããã«ãªãã¾ãã
ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ ã使ç¨ããã«ã¯ãçµã¿è¾¼ã¿è¦ç´ ã使ç¨ãã¾ãããã«ã¹ã¿ã åã is
屿§ã®å¤ã¨ãã¦ä½¿ç¨ãã¾ãã
èªå¾åã«ã¹ã¿ã è¦ç´ ãç¬èªã«ä½æãã¦ä½¿ç¨ããã«ã¯ãçµã¿è¾¼ã¿ã® HTML è¦ç´ ã¨åæ§ã«ã«ã¹ã¿ã åã使ç¨ãã¾ãã
<popup-info>
<!-- è¦ç´ ã®ä¸èº« -->
</popup-info>
屿§ã®å¤æ´ã¸ã®å¿ç
çµã¿è¾¼ã¿è¦ç´ ã¨åæ§ã«ãã«ã¹ã¿ã è¦ç´ ã HTML 屿§ã使ç¨ãã¦è¦ç´ ã®åä½ãè¨å®ãããã¨ãã§ãã¾ãã屿§ã广çã«ä½¿ç¨ããã«ã¯ãè¦ç´ ã屿§å¤ã®å¤æ´ã«å¯¾å¿ã§ããªããã°ãªãã¾ããããããå®ç¾ããã«ã¯ãã«ã¹ã¿ã è¦ç´ ãå®è£ ããã¯ã©ã¹ã«ä»¥ä¸ã®ã¡ã³ãã¼ã追å ããå¿ è¦ãããã¾ãã
observedAttributes
ã¨ããååã®éçããããã£ãããã¯ããã®è¦ç´ ã夿´éç¥ãå¿
è¦ã¨ãããã¹ã¦ã®å±æ§ã®ååãå«ãé
åã§ãªããã°ãªãã¾ãããattributeChangedCallback()
ã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ã®å®è£
ãattributeChangedCallback()
ã³ã¼ã«ããã¯ã¯ãè¦ç´ ã® observedAttributes
ããããã£ã«ãªã¹ããããååã®å±æ§ã追å ãä¿®æ£ãåé¤ãç½®æããããã³ã«å¼ã³åºããã¾ãã
ã³ã¼ã«ããã¯ã«ã¯ 3 ã¤ã®å¼æ°ã渡ããã¾ãã
ä¾ãã°ããã®èªå¾çãªè¦ç´ 㯠size
屿§ãç£è¦ããå¤ã夿´ãããéã«æ°æ§ã®å¤ãè¨é²ãã¾ãã
// è¦ç´ ã®ããã®ã¯ã©ã¹ã使
class MyCustomElement extends HTMLElement {
static observedAttributes = ["size"];
constructor() {
super();
}
attributeChangedCallback(name, oldValue, newValue) {
console.log(
`Attribute ${name} has changed from ${oldValue} to ${newValue}.`,
);
}
}
customElements.define("my-custom-element", MyCustomElement);
è¦ç´ ã® HTML 宣è¨ã«ç£è¦ããã屿§ãå«ã¾ãã¦ããå ´åããã®å±æ§ãåæåãããå¾ã«ãè¦ç´ ã®å®£è¨ãæåã«è§£éãããæç¹ã§ attributeChangedCallback()
ãå¼ã³åºããããã¨ã« 注æãã¦ãã ããã ãããã£ã¦ã以ä¸ã®ä¾ã§ã¯ããã¨ã屿§ããã®å¾å¤æ´ããããã¨ããªãã£ãã¨ãã¦ããDOM ãè§£éãããæç¹ã§ attributeChangedCallback()
ãå¼ã³åºããã¾ãã
<my-custom-element size="100"></my-custom-element>
attributeChangedCallback()
ã®ä½¿ç¨ã示ãå®å
¨ãªä¾ã«ã¤ãã¦ã¯ããã®ãã¼ã¸ã®ã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ãåç
§ãã¦ãã ããã
HTML è¦ç´ ã«çµã¿è¾¼ã¾ããè¦ç´ ã¯ããããã¼ãããç¡å¹ãããèªã¿åãå°ç¨ããªã©ãæ§ã ãªç¶æ ãåãã¾ãã ãããã®ç¶æ ã®ä¸é¨ã¯ãHTML ã¾ã㯠JavaScript ã使ç¨ãã¦å±æ§ã¨ãã¦è¨å®ã§ãã¾ãããå é¨çãªãã®ããããè¨å®ã§ããªããã®ãããã¾ãã å¤é¨ã¾ãã¯å é¨ã«é¢ãããããããã®ç¶æ ã«ã¯é常ãç¹å®ã®ç¶æ ã«ããè¦ç´ ã鏿ããã¹ã¿ã¤ã«ãé©ç¨ããããã«ä½¿ç¨ã§ãã対å¿ãã CSS æ¬ä¼¼ã¯ã©ã¹ãåå¨ãã¾ãã
ã¾ããèªå¾åã«ã¹ã¿ã è¦ç´ ï¼çµã¿è¾¼ã¿è¦ç´ ããã¼ã¹ã«ããè¦ç´ ãé¤ãï¼ã§ã¯ãæ¬ä¼¼ã¯ã©ã¹é¢æ° :state()
ã使ç¨ãã¦ç¶æ
ãå®ç¾©ããããã«å¯¾ãã¦é¸æãè¡ããã¨ãã§ãã¾ãã 以ä¸ã®ã³ã¼ãã§ã¯ãå
é¨ç¶æ
"collapsed
" ãæã¤èªå¾åã«ã¹ã¿ã è¦ç´ ã®ä¾ã使ç¨ãã¦ããã®åä½ã示ãã¦ãã¾ãã
collapsed
ã®ç¶æ
ã¯ãè¦ç´ ã®å¤ããã¯è¦ããªãè«çå¤ããããã£ï¼ã»ãã¿ã¼ã¨ã²ãã¿ã¼ã¡ã½ããä»ãï¼ã¨ãã¦è¡¨ç¾ããã¾ãã ãã®ç¶æ
ã CSS ã§é¸æã§ããããã«ããããã«ãã«ã¹ã¿ã è¦ç´ ã¯æåã®ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ HTMLElement.attachInternals()
ãå¼ã³åºããElementInternals
ãªãã¸ã§ã¯ããè£
çãã¾ããããã«ãããElementInternals.states
ããããã£ãéã㦠CustomStateSet
ã«ã¢ã¯ã»ã¹ã§ããããã«ãªãã¾ãã ï¼å
é¨ã§ï¼æãããã¾ããç¶æ
ã®ã»ãã¿ã¼ã¯ãç¶æ
ã true
ã§ããã° CustomStateSet
ã«èå¥å hidden
ã追å ããç¶æ
ã false
ã§ããã°é¤å»ãã¾ãã èå¥åã¯åãªãæååã§ãããã®å ´åãhidden
ã¨å¼ã³ã¾ããããcollapsed
ã¨èªãã§ãåãããã«æ©è½ãã¾ãã
class MyCustomElement extends HTMLElement {
constructor() {
super();
this._internals = this.attachInternals();
}
get collapsed() {
return this._internals.states.has("hidden");
}
set collapsed(flag) {
if (flag) {
// Existence of identifier corresponds to "true"
this._internals.states.add("hidden");
} else {
// Absence of identifier corresponds to "false"
this._internals.states.delete("hidden");
}
}
}
// Register the custom element
customElements.define("my-custom-element", MyCustomElement);
ã«ã¹ã¿ã è¦ç´ ã® CustomStateSet
(this._internals.states
) ã«è¿½å ãããèå¥åã使ç¨ãã¦ãè¦ç´ ã®ã«ã¹ã¿ã ç¶æ
ã¨ç
§åãããã¨ãã§ãã¾ãã ããã¯ã:state()
æ¬ä¼¼ã¯ã©ã¹ã«èå¥åãæ¸¡ãã¨ç
§åããã¾ãã ä¾ãã°ãä¸è¨ã§ã¯ãhidden
ã»ã¬ã¯ã¿ã¼ã使ç¨ãã¦ãhidden
ç¶æ
ã true
ï¼ãããã£ã¦ãè¦ç´ ãcollapsed
ç¶æ
ï¼ã§ãããã¨ã鏿ããå¢çç·ãåé¤ãã¾ãã
my-custom-element {
border: dashed red;
}
my-custom-element:state(hidden) {
border: none;
}
:state()
æ¬ä¼¼ã¯ã©ã¹ã :host()
æ¬ä¼¼ã¯ã©ã¹é¢æ°å
ã§ä½¿ç¨ããã¨ãã«ã¹ã¿ã è¦ç´ ã®ã·ã£ã㦠DOM å
ã®ã«ã¹ã¿ã ç¶æ
ã¨ç
§åãããã¨ãã§ãã¾ãã ããã«ã:state()
æ¬ä¼¼ã¯ã©ã¹ã ::part()
æ¬ä¼¼è¦ç´ ã®å¾ã§ä½¿ç¨ãããã¨ã§ãç¹å®ã®ç¶æ
ã«ããã«ã¹ã¿ã è¦ç´ ã®ã·ã£ãã¦ãã¼ãã¨ç
§åãããã¨ãã§ãã¾ãã
CustomStateSet
ã«ã¯ããããã©ã®ããã«åä½ããã®ãã示ãããã¤ãã®ã©ã¤ããµã³ãã«ãããã¾ãã
ãã®ã¬ã¤ãã®æ®ãã®é¨åã§ã¯ãããã¤ãã®ã«ã¹ã¿ã è¦ç´ ã®ä¾ãè¦ã¦ããã¾ãã ãããã®ä¾ã®ãã¹ã¦ãããã³ãã®ä»ã®ã½ã¼ã¹ã¯ãweb-components-examples ãªãã¸ããªã¼ã§åç §ã§ãã¾ããã¾ãããã¹ã¦ãã©ã¤ãã§ç¢ºèªããã«ã¯ãhttps://mdn.github.io/web-components-examples/ ã«ã¢ã¯ã»ã¹ãã¦ãã ããã
èªå¾ã«ã¹ã¿ã è¦ç´ã¾ããèªå¾ã«ã¹ã¿ã è¦ç´ ã®ä¾ãè¦ã¦ã¿ã¾ãããã<popup-info>
ã«ã¹ã¿ã è¦ç´ ã¯ãç»åã¢ã¤ã³ã³ã¨ããã¹ãæååã屿§ã¨ãã¦åããã¢ã¤ã³ã³ã«ãã©ã¼ã«ã¹ããã¨ãããã¹ãããããã¢ããæ
å ±ããã¯ã¹ã«è¡¨ç¤ºããããã«ã³ã³ããã¹ãå
ã®æ
å ±ãæä¾ãã¾ãã
æåã« HTMLElement
ã¯ã©ã¹ãç¶æ¿ã㦠PopupInfo
ã¨ããã¯ã©ã¹ãå®ç¾©ãã JavaScript ãã¡ã¤ã«ã§ãã
// è¦ç´ ã®ããã®ã¯ã©ã¹ã使
class PopupInfo extends HTMLElement {
constructor() {
// ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ super ãå¸¸ã«æåã«å¼ã³åºã
super();
}
connectedCallback() {
// ã·ã£ãã¦ã«ã¼ããçæ
const shadow = this.attachShadow({ mode: "open" });
// span è¦ç´ ãçæ
const wrapper = document.createElement("span");
wrapper.setAttribute("class", "wrapper");
const icon = document.createElement("span");
icon.setAttribute("class", "icon");
icon.setAttribute("tabindex", 0);
const info = document.createElement("span");
info.setAttribute("class", "info");
// 屿§ã®ä¸èº«ãåå¾ããæ
å ± span ã®ä¸ã«å
¥ãã
const text = this.getAttribute("data-text");
info.textContent = text;
// ã¢ã¤ã³ã³ãæ¿å
¥
let imgUrl;
if (this.hasAttribute("img")) {
imgUrl = this.getAttribute("img");
} else {
imgUrl = "img/default.png";
}
const img = document.createElement("img");
img.src = imgUrl;
icon.appendChild(img);
// ããããã® CSS ãçæãã¦ã·ã£ã㦠DOM ã«é©ç¨
const style = document.createElement("style");
console.log(style.isConnected);
style.textContent = `
.wrapper {
position: relative;
}
.info {
font-size: 0.8rem;
width: 200px;
display: inline-block;
border: 1px solid black;
padding: 10px;
background: white;
border-radius: 10px;
opacity: 0;
transition: 0.6s all;
position: absolute;
bottom: 20px;
left: 10px;
z-index: 3;
}
img {
width: 1.2rem;
}
.icon:hover + .info, .icon:focus + .info {
opacity: 1;
}
`;
// çæè¦ç´ ãã·ã£ã㦠DOM ã«çµã³ã¤ãã
shadow.appendChild(style);
console.log(style.isConnected);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);
}
}
åè¿°ã®ã³ã¼ãã¹ããããã¯ã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¼ï¼constructor()
ï¼ã®å®ç¾©ãå«ãã§ãã¾ããããã§ã¯å¸¸ã« super()
ãæåã«å¼ã³åºããæ£ãããããã¿ã¤ããã§ã¼ã³ã確ç«ãããããã«ãã¾ãã
connectedCallback()
ã¡ã½ããå
ã§ãè¦ç´ ã DOM ã«æ¥ç¶ãããéã«ãã®è¦ç´ ãæã¤ãã¹ã¦ã®æ©è½ãå®ç¾©ãã¾ãããã®ä¾ã§ã¯ãã·ã£ãã¦ã«ã¼ããã«ã¹ã¿ã è¦ç´ ã«å²ãå½ã¦ãDOM æä½ã使ç¨ãã¦è¦ç´ ã®å
é¨ã·ã£ãã¦ã«ã¼ãæ§é ã使ãã¾ãï¼ããã¦ã·ã£ãã¦ã«ã¼ãã«å²ãå½ã¦ã¾ãï¼ãæå¾ã«ãã·ã£ãã¦ã«ã¼ãã«ããã¤ãã® CSS ãå²ãå½ã¦ã¦ã¹ã¿ã¤ã«è¨å®ãã¾ããè¦ç´ ã®å±æ§ã¯ DOM ã«æ¥ç¶ãããã¾ã§å©ç¨ã§ããªããããã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯å¦çã¯ãã¾ãããã¾ããã
æå¾ã«ãã«ã¹ã¿ã è¦ç´ ã CustomElementRegistry
ã«ç»é²ãã¾ããåè¿°ã® define()
ã使ç¨ãã¦ã弿°ã§è¦ç´ åã¨ãã®æ©è½ãå®ç¾©ããã¯ã©ã¹åãæå®ãã¾ãã
customElements.define("popup-info", PopupInfo);
ããã«ãã£ã¦è¦ç´ ããã¼ã¸ã§ä½¿ããããã«ãªãã¾ããã HTML å ã§ä¸è¨ã®ããã«ä½¿ç¨ãããã¨ãã§ãã¾ãã
<popup-info
img="img/alt.png"
data-text="Your card validation code (CVC)
is an extra security feature â it is the last 3 or 4 numbers on the
back of your card."></popup-info>
å
é¨ã¹ã¿ã¤ã«ã¨å¤é¨ã¹ã¿ã¤ã«
ä¸è¨ã®ä¾ã§ã¯ã<style>
è¦ç´ ãç¨ãã¦ã·ã£ã㦠DOM ã«ã¹ã¿ã¤ã«ãé©ç¨ãã¾ãããã代ããã« <link>
è¦ç´ ããå¤é¨ã¹ã¿ã¤ã«ã·ã¼ããåç
§ãããã¨ãå¯è½ã§ãããã®ä¾ã§ã¯ãå¤é¨ã¹ã¿ã¤ã«ã·ã¼ãã使ç¨ããããã« <popup-info>
ã«ã¹ã¿ã è¦ç´ ã夿´ãã¾ãã
ãã¡ããã¯ã©ã¹å®ç¾©ã§ãã
// è¦ç´ ã®ããã®ã¯ã©ã¹ã使
class PopupInfo extends HTMLElement {
constructor() {
// ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ super ãå¸¸ã«æåã«å¼ã³åºã
super();
}
connectedCallback() {
// ã·ã£ãã¦ã«ã¼ããçæ
const shadow = this.attachShadow({ mode: "open" });
// span è¦ç´ ãçæ
const wrapper = document.createElement("span");
wrapper.setAttribute("class", "wrapper");
const icon = document.createElement("span");
icon.setAttribute("class", "icon");
icon.setAttribute("tabindex", 0);
const info = document.createElement("span");
info.setAttribute("class", "info");
// 屿§ã®ä¸èº«ãåå¾ããæ
å ± span ã®ä¸ã«å
¥ãã
const text = this.getAttribute("data-text");
info.textContent = text;
// ã¢ã¤ã³ã³ãæ¿å
¥
let imgUrl;
if (this.hasAttribute("img")) {
imgUrl = this.getAttribute("img");
} else {
imgUrl = "img/default.png";
}
const img = document.createElement("img");
img.src = imgUrl;
icon.appendChild(img);
// å¤é¨ã¹ã¿ã¤ã«ã·ã¼ããã·ã£ã㦠DOM ã«é©ç¨
const linkElem = document.createElement("link");
linkElem.setAttribute("rel", "stylesheet");
linkElem.setAttribute("href", "style.css");
// çæããè¦ç´ ãã·ã£ã㦠DOM ã«çµã³ã¤ãã
shadow.appendChild(linkElem);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);
}
}
ããã¯ãå
ã® <popup-info>
ã®ä¾ã¨ã»ã¼åãã§ãããå¤é¨ã¹ã¿ã¤ã«ã·ã¼ãã«ãªã³ã¯ããããã«ãã·ã£ã㦠DOM ã«è¿½å ãã <link>
è¦ç´ ã使ç¨ãã¦ããç¹ãç°ãªãã¾ãã
ãªãã <link>
è¦ç´ ã¯ã·ã£ãã¦ã«ã¼ãã®æç»ããããã¯ããªãã®ã§ãã¹ã¿ã¤ã«ã·ã¼ãã®ãã¼ãä¸ã«ã¹ã¿ã¤ã«ä»ãããã¦ããªãã³ã³ãã³ã (FOUC) ãä¸ç¬è¡¨ç¤ºããããããããªããã¨ã«æ³¨æãã¦ãã ããã
æè¿ã®ãã©ã¦ã¶ã¼ã®å¤ãã¯ãå
±éã®ãã¼ãããã¯ãã¼ã³ãããããããã¯åä¸ã®ããã¹ããæã¤ <style>
ã¿ã°ã«å¯¾ãã¦ãåä¸ã®ãããã³ã°ã¹ã¿ã¤ã«ã·ã¼ããå
±æã§ããããã«ããæé©åãå®è£
ãã¦ãã¾ãããã®æé©åã«ãã£ã¦ãå¤é¨ã¹ã¿ã¤ã«ã§ãå
é¨ã¹ã¿ã¤ã«ã§ãæ§è½ã¯åç¨åº¦ã«ãªãã¯ãã§ãã
ããã§ããã 1 ã¤ã®çµã¿è¾¼ã¿è¦ç´ ã®ä¾ãè¦ã¦ã¿ã¾ãããããã®ä¾ã¯ãçµã¿è¾¼ã¿ã® <ul>
è¦ç´ ãæ¡å¼µãã¦ããªã¹ãã¢ã¤ãã ãå±éã»åç´ããããããã«ãã¾ãã
ã¡ã¢: ã«ã¹ã¿ã çµã¿è¾¼ã¿è¦ç´ ã®å®è£
ã«é¢ããæ³¨æäºé
ã«ã¤ãã¦ã¯ãis
屿§ã®ãªãã¡ã¬ã³ã¹ãåç
§ãã¦ãã ããã
ã¾ãå§ãã«ãããã¾ã§ã¨åæ§ã®æ¹æ³ã§ã¯ã©ã¹è¦ç´ ãå®ç¾©ãã¾ãã
// è¦ç´ ã®ããã®ã¯ã©ã¹ã使
class ExpandingList extends HTMLUListElement {
constructor() {
// ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ super ãå¸¸ã«æåã«å¼ã³åºã
// super() ã®è¿å¤ã¯ãã®è¦ç´ ã¸ã®åç
§
self = super();
}
connectedCallback() {
// ãã®ã«ã¹ã¿ã ul è¦ç´ ã®åã§ãã ul ããã³ li è¦ç´ ãåå¾ãã
// li è¦ç´ ã¯ããã®ä¸ã« ul ãããå ´åãã³ã³ããã¼ã¨ãã¦æ©è½ãã
const uls = Array.from(self.querySelectorAll("ul"));
const lis = Array.from(self.querySelectorAll("li"));
// ãã¹ã¦ã®åã® ul ãé ã
// ãããã®ãªã¹ãã¯ãã¦ã¼ã¶ã¼ãä¸ä½ã¬ãã«ã®ã³ã³ããã¼ãã¯ãªãã¯ããã¨ãã«è¡¨ç¤ºããã
uls.forEach((ul) => {
ul.style.display = "none";
});
// ulå
ã®liè¦ç´ ãããããè¦ã¦ãã
lis.forEach((li) => {
// ãã® li ã« ul ãåè¦ç´ ã¨ãã¦ããå ´åãã¯ãªãã¯ãã³ãã©ã¼ã追å ãã
if (li.querySelectorAll("ul").length > 0) {
// ã¹ã¿ã¤ã«è¨å®ã§ä½¿ç¨ã§ãã屿§ã追å ãã
// éãã»éããã¢ã¤ã³ã³ã表示ããã
li.setAttribute("class", "closed");
// li è¦ç´ ã®ããã¹ããæ°ãã span è¦ç´ ã§å²ããã¨ã§ã
// span ã«ã¹ã¿ã¤ã«ãã¤ãã³ããã³ãã©ã¼ãå²ãå½ã¦ããã¨ãã§ãã
const childText = li.childNodes[0];
const newSpan = document.createElement("span");
// li ãã span ã«ããã¹ããã³ãã¼ããã«ã¼ã½ã«ã¹ã¿ã¤ã«ãè¨å®
newSpan.textContent = childText.textContent;
newSpan.style.cursor = "pointer";
// ãã® span ã«ã¯ãªãã¯ãã³ãã©ã¼ã追å
newSpan.addEventListener("click", (e) => {
// span è¦ç´ ã®æ¬¡å
å¼è¦ç´ 㯠ul ã§ããã¯ã
const nextul = e.target.nextElementSibling;
// è¡¨ç¤ºç¶æ
ãåãæ¿ããul ã® class 屿§ãæ´æ°
if (nextul.style.display == "block") {
nextul.style.display = "none";
nextul.parentNode.setAttribute("class", "closed");
} else {
nextul.style.display = "block";
nextul.parentNode.setAttribute("class", "open");
}
});
// span ã追å ããli ãã裸ã®ããã¹ããã¼ããé¤å»
childText.parentNode.insertBefore(newSpan, childText);
childText.parentNode.removeChild(childText);
}
});
}
}
ãªããä»å㯠HTMLElement
ã§ã¯ãªããHTMLUListElement
ãæ¡å¼µãã¦ãã¾ãã ã¤ã¾ãããªã¹ãã®æ¢å®ã®åä½ãå¾ãããç¬èªã®ã«ã¹ã¿ãã¤ãºã®ã¿ãå®è£
ããã°ããã¨ãããã¨ã§ãã
ååã¨åæ§ã«ãã³ã¼ãã®ã»ã¨ãã©ã¯ connectedCallback()
ã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯å
ã«ããã¾ãã
次ã«ãååã¨åæ§ã« define()
ã¡ã½ããã使ç¨ãã¦è¦ç´ ãç»é²ãã¾ãããä»åã¯ãã«ã¹ã¿ã è¦ç´ ãç¶æ¿ããè¦ç´ ã®è©³ç´°ãè¨è¼ãã options ãªãã¸ã§ã¯ããå«ãã¾ãã
customElements.define("expanding-list", ExpandingList, { extends: "ul" });
ã¦ã§ãææ¸å ã§çµã¿è¾¼ã¿è¦ç´ ã使ç¨ããã¨ãã¾ãå°ãéã£ãè¦ãæ¹ã«ãªãã¾ãã
<ul is="expanding-list">
â¦
</ul>
é常ã®ããã« <ul>
ã使ç¨ãã¦ãã¾ãããã«ã¹ã¿ã è¦ç´ ã®ååã is
屿§ã§æå®ããã¦ãã¾ãã
ãã®å ´åãDOM ãå®å
¨ã«è§£éãããå¾ã«ã«ã¹ã¿ã è¦ç´ ãå®ç¾©ããã¹ã¯ãªãããå®è¡ãããããã«ä¿è¨¼ããå¿
è¦ãããã¾ããconnectedCallback()
ã¯å±éããããªã¹ãã DOM ã«è¿½å ãããã¨åæã«å¼ã³åºããã¾ããããã®æç¹ã§ã¯åè¦ç´ ã¯ã¾ã 追å ããã¦ããªããããquerySelectorAll()
ã®å¼ã³åºãã§ã¯ä½ãè¦ã¤ããã¾ããããããä¿è¨¼ããä¸ã¤ã®æ¹æ³ã¯ãã¹ã¯ãªãããè¨è¼ããè¡ã« defer 屿§ã追å ãããã¨ã§ãã
<script src="main.js" defer></script>
ã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯
ããã¾ã§ã¯ãconnectedCallback()
ã¨ããã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ã 1 ã¤ã ãåä½ãã¦ããã®ãè¦ã¦ãã¾ãããæå¾ã®ä¾ã§ãã <custom-square>
ã§ã¯ãä»ã«ãããã¤ãè¦ã¦ããã¾ãããã®ä¾ã§ã¯ãèªå¾åã®ã«ã¹ã¿ã è¦ç´ <custom-square>
ãç´¹ä»ãã¾ããããã¯ãååä»ãã® 2 ã¤ã®å±æ§ "size"
ããã³ "color"
ã«ãã£ã¦ãµã¤ãºã¨è²ã決å®ãããåè§å½¢ãæç»ãã¾ãã
ã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ãè¦ç´ ã«ã·ã£ã㦠DOM ãå²ãå½ã¦ã空㮠<div>
ããã³ <style>
è¦ç´ ãã·ã£ãã¦ã«ã¼ãã«è¿½å ãã¾ãã
constructor() {
// ã³ã³ã¹ãã©ã¯ã¿ã¼ã§ã¯ super ãå¸¸ã«æåã«å¼ã³åºã
super();
const shadow = this.attachShadow({ mode: "open" });
const div = document.createElement("div");
const style = document.createElement("style");
shadow.appendChild(style);
shadow.appendChild(div);
}
ãã®ä¾ã®ä¸»è¦ãªæ©è½ã¯ updateStyle()
ã§ããããã¯è¦ç´ ãåå¾ããã·ã£ãã¦ã«ã¼ããåå¾ãããã® <style>
è¦ç´ ãè¦ã¤ãã¦ãwidth
, height
, background-color
ããã®ã¹ã¿ã¤ã«ã«è¿½å ãã¾ãã
function updateStyle(elem) {
const shadow = elem.shadowRoot;
shadow.querySelector("style").textContent = `
div {
width: ${elem.getAttribute("size")}px;
height: ${elem.getAttribute("size")}px;
background-color: ${elem.getAttribute("color")};
}
`;
}
å®éã®æ´æ°ã¯ãã¹ã¦ãã¡ã½ããã¨ãã¦ã¯ã©ã¹å®ç¾©å
ã«é
ç½®ããã¦ããã©ã¤ããµã¤ã¯ã«ã³ã¼ã«ããã¯ã«ãã£ã¦å¦çããã¾ãã connectedCallback()
ã¯ãè¦ç´ ã DOM ã«è¿½å ããããã³ã«å®è¡ããã¾ããããã§ã¯ã updateStyle()
颿°ãå®è¡ãã¦ãæ£æ¹å½¢ããã®å±æ§ã§å®ç¾©ãããã¹ã¿ã¤ã«ã«ãªã£ã¦ãããã¨ã確èªãã¾ãã
connectedCallback() {
console.log("Custom square element added to page.");
updateStyle(this);
}
disconnectedCallback()
ããã³ adoptedCallback()
ã³ã¼ã«ããã¯ã¯ãè¦ç´ ã DOM ããåé¤ãããããå¥ã®ãã¼ã¸ã«ç§»åãããã¨ãã«éç¥ããåç´ãªã¡ãã»ã¼ã¸ãã³ã³ã½ã¼ã«ã«è¨é²ãã¾ãã
disconnectedCallback() {
console.log("Custom square element removed from page.");
}
adoptedCallback() {
console.log("Custom square element moved to new page.");
}
attributeChangedCallback()
ã³ã¼ã«ããã¯ã¯ãè¦ç´ ã®å±æ§ã® 1 ã¤ãä½ããã®æ¹æ³ã§å¤æ´ããããã³ã«å®è¡ããã¾ãããã®å¼æ°ãããããããã«ã屿§ã屿§ã®ååãããã³å¤ã屿§å¤ã¨æ°ãã屿§å¤ãåå¥ã«æä½ãããã¨ãã§ãã¾ãããã ãããã®å ´åã¯ãupdateStyle()
颿°ãå度å®è¡ãã¦ãæ°ããå¤ã«å¾ã£ã¦æ£æ¹å½¢ã®ã¹ã¿ã¤ã«ãæ´æ°ãããããã«ãã¾ãã
attributeChangedCallback(name, oldValue, newValue) {
console.log("Custom square element attributes changed.");
updateStyle(this);
}
ãã屿§ã夿´ãããã¨ãã«èµ·åãã attributeChangedCallback()
ã³ã¼ã«ããã¯ãåå¾ããã«ã¯ããã®å±æ§ãç£è¦ããå¿
è¦ããããã¨ã«æ³¨æãã¦ãã ãããããã¯ãã«ã¹ã¿ã è¦ç´ ã¯ã©ã¹å
ã§ static get observedAttributes()
ã¡ã½ãããå®ç¾©ãããã¨ã«ãã£ã¦è¡ããã¾ããããã¯ãç£è¦ããã屿§ã®ååãå«ãé
åãè¿ãããã«ãã¦ãã ããã
static get observedAttributes() {
return ["color", "size"];
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4