ãšã³ããªãŒ
ãããã€ãååããããŠWebã³ã³ããŒãã³ãã«é¢ããäžé£ã®èšäºã®ç¶ãã玹ä»ããŸãããã®æåã®éšåã¯ããããå ¥æã§ããŸãã
ãã®èšäºã§ã¯ã2018幎3æ1æ¥ä»ãã®Shadow DOMïŒã·ã£ããŠDOMïŒããŒãžã§ã³ã®ä»æ§ã«çŠç¹ãåœãŠãŸãã ææ°ã®ãã©ããä»æ§ã¯ ã2018幎3æ8æ¥ä»ãã§ãã
ã·ã£ããŠDOMã®APIã䜿çšãããšãã·ã£ããŠããªãŒãšåŒã°ããããªãŒæ§é ã«ããŒã¯ã¢ãããé 眮ããããšã§ããŒãžã®ã³ã³ãã³ããã«ãã»ã«åã§ããŸãã DOMã®éåžžã®åå«ã Webã³ã³ããŒãã³ããäœæããããã®ãã¹ãŠã®APIã®ã³ã³ããã¹ãã«ããããã®APIã¯ãã³ã³ããŒãã³ãã®å éšå®è£ ãé ãã ãã§ãªããæå°éã®åŽåã§ã¹ã¿ã€ã«ãã«ãã»ã«åããæ©äŒãæäŸããŸãã
ã·ã£ããŠDOMã¯ãå€ãã®èŠçŽ ã®å éšå®è£ ã®ããã«ãã©ãŠã¶ã§ãã§ã«äœ¿çšãããŠããŸãã äŸãã°
ã³ã³ãœãŒã«ã§è¡šç€ºãããšãåäžã®èŠçŽ ã§ã¯ãªããã·ã£ããŠDOMã®éåžžã®HTMLèŠçŽ ã®ããªãŒæ§é ã§ããããšãããããŸãã<input type=ârangeâ/>
åºæ¬çãªæŠå¿µ
ã·ã£ããŠDOMã®æŠå¿µã®éèŠãªæŠå¿µã¯ã ã·ã£ããŠããªãŒã§ããããã¯ãããã¥ã¡ã³ãã«ã¬ã³ããªã³ã°ãããŸãããDOMããªãŒã«ã¯ã¬ã³ããªã³ã°ãããªãããµãããªãŒãã§ãã ç§ã«ãšã£ãŠæãç°¡åãªããšã¯ãã·ã£ããŠããªãŒãããã¥ã¡ã³ãããŒããšããã¥ã¡ã³ããã©ã°ã¡ã³ãã®éã®äœããšèããããšã§ããã
ã·ã£ããŠããªãŒã®ã«ãŒãèŠçŽ ã¯ã·ã£ããŠã«ãŒãã§ãã ããã¯ã .attachShadowïŒobjïŒã¡ãœãããåŒã³åºãããããŒãã§ããobjã¯ã ã¢ãŒãããããã£ãå«ãèšå®ãªããžã§ã¯ãã§ããã·ã£ããŠDOMãžã®ã¢ã¯ã»ã¹ã¢ãŒãã§ã ãopenãã«èšå®ã§ããŸãïŒã·ã£ããŠDOMãžã®ã¢ã¯ã»ã¹ã¯ã .shadowRootããããã£ã䜿çšããã¡ã€ã³ããã¥ã¡ã³ãã®ïŒãŸãã¯ãclosedã ïŒãshadowRootãä»ããã¢ã¯ã»ã¹ã¯nullãè¿ããŸãïŒãã ãã®èšäºã§ã¯ ã ã¯ããŒãºã¢ãŒãã«çå£ã«äŸåããæå³ããªãçç±ã«ã€ããŠè©³ãã説æããŸã ã 2018幎3æ2æ¥ä»ã®ãã©ããä»æ§ã§ã¯ã å§ä»»ããããã©ãŒã«ã¹ãã·ã£ããŠãã¹ãããã·ã£ããŠã«ãŒãã«å§ä»»ãããïŒtrue / falseïŒãã©ãããèšå®ããèšå®ãæäŸãããŸãããã6æ¥åŸã«ãã®æŠå¿µã¯ä»æ§ããåé€ãããŸããã
.attachShadowïŒïŒã¡ãœããã¯ãã·ã£ããŠããªãŒãããŒãã«ã¢ã¿ãããã ShadowRootãªããžã§ã¯ããè¿ããŸãã
ã·ã£ããŠã«ãŒããå±ããããªãŒã¯ã©ã€ãããªãŒãšåŒã°ããã¡ãªã¿ã«ã©ã€ãããªãŒã¯å¥ã®ã·ã£ããŠããªãŒã§ããå ŽåããããŸãã
ã¹ããã
ã·ã£ããŠããªãŒã«ã¯ã¹ãããèŠçŽ ãå«ãŸããå Žåãããããã®èŠçŽ ïŒdocumentFragmentã®é¡äŒŒèŠçŽ ïŒãDOMã§ã¬ã³ããªã³ã°ããããšãã¹ãããã¯ãã®ã³ã³ãã³ãã«çœ®ãæããããŸãã
ã¹ãããèŠçŽ ã®æäœã®ç¹æ®ãªã±ãŒã¹ã¯ã nameå±æ§ã§å€ãæå®ãããŠãããã©ããã«ãã£ãŠç°ãªããŸãã
nameå±æ§ã®å€ãèšå®ãããŠããå Žå
ã¹ãããèŠçŽ ã®ååå±æ§ã«å€ãå²ãåœãŠããããšãããã¥ã¡ã³ãã®ã¬ã³ããªã³ã°æã®ã¹ãããèŠçŽ ã¯ãã¹ãããèŠçŽ ã®ååå±æ§ã®å€ã«çããå€ã«èšå®ãããã¹ãããå±æ§ãæã€ããã¥ã¡ã³ãïŒã©ã€ãããªãŒïŒã®èŠçŽ ã«çœ®ãæããããŸãã
äŸãšããŠãåã®èšäºã®å·çäžã«ã³ã³ãã€ã«ããããŠãŒã¶ãŒèŠçŽ ã¿ãã®ã³ãŒããåãäžãã次ã®å€æŽãå ããŸããã
class TabNavigationItem extends HTMLElement { constructor() { super(); this._target = null; this.attachShadow({ mode: 'open' }); } //... }
ã·ã£ããŠDOMãäœæãããã³ã³ã¹ãã©ã¯ã¿ãŒã«ã¢ã¿ãããããŸãã ããã§ãã·ã£ããŠã«ãŒããžã®ã¢ã¯ã»ã¹ãthis.shadowRootåŒã³åºããä»ããŠå¯èœã«ãªããŸãã
次ã®ã¹ãããã§ã¯ããŠãŒã¶ãŒèŠçŽ ã®ã¬ã€ã¢ãŠããå€æŽããããšã«ããã.renderïŒïŒã¡ãœãããå€æŽããŸããã
render() { if(!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <a href="#${this._target}"><slot name="nav"></slot></a> `; }
ããŒã¯ã¢ãããthis.shadowRootãªããžã§ã¯ãã®.innerHTMLããããã£ã®å€ã«æž¡ãããããšã«æ³šæããããšãéèŠã§ãã
ããŒã¯ã¢ããã§ãã«ã¹ã¿ã èŠçŽ ã䜿çšããå Žåãåäžã®æ¡ä»¶ã§ããã²ãŒã·ã§ã³èŠçŽ ã®å éšã³ã³ãã³ããèšå®ã§ããŸãããã¹ããããèŠçŽ ã¯ãã·ã£ããŠDOMã®ã¹ãããèŠçŽ ã®ååå±æ§ã®å€ãšçããã¹ãããå±æ§ãæã€å¿ èŠããããŸãïŒãã®äŸã§ã¯ãnavãïŒãããã§ãªãå Žåã¯è¡šç€ºãããŸããã
<tab-nav-item class="active" target="First tab"> <h1 slot="nav">First</h1> </tab-nav-item>
TabContentItemã¯ã©ã¹ã«åæ§ã®å€æŽãå ããŸãã
class TabContentItem extends HTMLElement { constructor() { super(); this._target = null; this.attachShadow({ mode: 'open' }); } render() { if(!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <div> <slot name="tab"></slot> </div> `; } }
ã·ã£ããŠDOMãå«ãŸããŠãããããã³ã³ãã³ãå±æ§ã䜿çšããŠã¿ãã®ã³ã³ãã³ãã衚瀺ããå¿ èŠããªããªããŸããã
ãã®ãããªã«ã¹ã¿ã èŠçŽ ã®äœ¿çšã¯æ¬¡ã®ããã«ãªããŸãã
<tab-element> <nav> <tab-nav-item class="active" target="First tab"> <h1 slot="nav">First</h1></tab-nav-item> <tab-nav-item target="Second tab"><h2 slot="nav">Second</h2></tab-nav-item> <tab-nav-item target="Third tab"><h3 slot="nav">Third</h3></tab-nav-item> </nav> <tab-content-item class='active' target="First tab"> <div slot="tab"> <h3>Hi, I'm the first</h3> <h1>TAB</h1> </div> </tab-content-item> <tab-content-item target="Second tab"> <p slot="tab">second one!</p> </tab-content-item> <tab-content-item target="Third tab"> <style slot="tab"> .test { border: 1px solid yellow; padding: 20px } </style> <div slot="tab"> <div class="test">I'm the third</div> </div> </tab-content-item> </tab-element>
ãã®äŸã¯ãã³ã³ããŒãã³ãã®ãŠãŒã¶ãŒãããã²ãŒã·ã§ã³èŠçŽ å ãšã¿ãã³ã³ãã³ãèŠçŽ å ã®äž¡æ¹ã§ä»»æã®ããŒã¯ã¢ããã転éã§ããããšã瀺ããŠããŸããããã®å Žåãããã®ãããªããŒã¯ã¢ããã®èŠçŽ ã«å¯Ÿããã¹ãããããŒãã³ã°ã®å¿ é ã®ååšãšãã圢ã§å¶éããããŸããŠãŒã¶ãŒèŠçŽ ããšã«åãå€ïŒã ç§ã®æèŠã§ã¯ãããã¯ã¹ãããèŠçŽ ã®2çªç®ã®åäœãæãŸããå Žåã§ãã
nameå±æ§ã®å€ãèšå®ãããŠããªãå Žå
ã¹ãããèŠçŽ ã®ååãæå®ãããŠããªãå Žåãããã©ã«ãã§ã¯ç©ºã®æååã«çãããªãããã®ãããªã¹ãããã¯ããã©ã«ãã®ã¹ããããšåŒã°ããŸã ã ã¬ã³ããªã³ã°æã«ãã¹ãããå±æ§ãæããªãèŠçŽ ã«çœ®ãæããããŸãã
ãããã£ãŠãã¬ã³ããŒã¡ãœããã§æå®ãããããŒã¯ã¢ããããååå±æ§ãšãã®å€ãåé€ããã¡ã€ã³ããã¥ã¡ã³ãã®ããŒã¯ã¢ããããã¹ãããå±æ§ãšãã®å€ãåé€ããŸãã ãããã£ãŠããŠãŒã¶ãŒèŠçŽ ã®2ã€ã®ã¿ã°ã®éã«ç€ºããããã¹ãŠã®ããŒã¯ã¢ããã¯ãããã©ã«ãã¹ãããã«åã蟌ãŸããŸãã ããŒã¯ã¢ããåé¢ã³ãŒãã¯ããã«ãããŸã ã
ã¹ã¿ã€ã«
ã·ã£ããŠDOMã®èŠçŽ ã®ã¹ã¿ã€ã«ã¿ã°å ã§æå®ãããã¹ã¿ã€ã«ã¯ããããã«éå®ãããŸãã å€éšç°å¢ããã®CSSã»ã¬ã¯ã¿ãŒã¯ãã·ã£ããŠDOMã®ã³ã³ãã³ãã«ã¯é©çšãããããããã£ãŠããã®ã¹ã¿ã€ã«ã¯æŒããŸãããããã«ãããç°¡åãªã»ã¬ã¯ã¿ãŒã䜿çšã§ããããã«ãªããŸããããã«ãããèšè¿°ã®å©äŸ¿æ§ã«å ããŠãããã©ãŒãã³ã¹ãåäžããŸãã
ã«ã¹ã¿ã Webã³ã³ããŒãã³ãã¯ã ãã¹ãã»ã¬ã¯ã¿ãŒã䜿çšããŠãã·ã£ããŠDOMã³ã³ããã¹ãããã¹ã¿ã€ã«ãèšå®ã§ããŸãã åæã«ããã®ãããªã»ã¬ã¯ã¿ãŒã®ã«ãŒã«ã¯ãã³ã³ããŒãã³ãã®å€éšã¹ã¿ã€ã«ã«ãã£ãŠæžãæããããšãã§ããŸããããã«ãããã³ã³ããŒãã³ãã䜿çšãããšãã«ã¹ã¿ã€ã«ãå€æŽã§ããŸãïŒäœ¿çšæã«å¿ èŠã«å¿ããŠèª¿æŽããŸãïŒã A ïŒãã¹ãïŒã»ã¬ã¯ã¿ãŒïŒã䜿çšãããšãã³ã³ããŒãã³ãã¯ããŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãšã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ãèŠèŠåããããã ãã«äœ¿çšãããã»ã¬ã¯ã¿ãŒãšäžèŽãããšãã«ãã¹ããã¹ã¿ã€ã«ã§ããŸãã ã³ã³ããã¹ãã«ããã¹ã¿ã€ã«èšå®ã䜿çšã§ããŸããã³ã³ããŒãã³ãã®ç¥å ã®äžéšãã»ã¬ã¯ã¿ãŒïŒç°å¢ã®ã¹ã¿ã€ã«èšå®ã«äœ¿çšïŒã«äžèŽããå Žåã«ã®ã¿ãã³ã³ããŒãã³ãã«äžèŽãããã¹ãã³ã³ããã¹ãïŒã»ã¬ã¯ã¿ãŒ ïŒã
ã¿ãããã³ããã©ã«ãã®å€éšã¹ã¿ã€ã«ã®åäœã決å®ããåå ãšãªãã¹ã¿ã€ã«ãåé€ããã·ã£ããŠDOMã§é衚瀺ã«ããããšã«ããŸããããã®ããã«ãTabNavigationItemã¯ã©ã¹ã®.renderïŒïŒã¡ãœããã®ããŒã¯ã¢ããå ã«ã¹ã¿ã€ã«ã¿ã°ãæ¿å ¥ããŸãã
render() { if (!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <style> :host{ padding: 10px; background-color: gray; border: 1px solid gray; } :host-context(.active) { background-color: #ccc; } a{ text-decoration: none; color: black; } </style> <a href="#${this._target}"><slot></slot></a> `; }
åæ§ã«ãTabContentItemã¯ã©ã¹ã®.renderïŒïŒã¡ãœããã®å ŽåïŒ
render() { if (!this.ownerDocument.defaultView) return; this.shadowRoot.innerHTML = ` <style> :host { display: none; padding: 20px; width: 100%; height: 50px; } :host-context(.active){ display: block; } </style> <div><slot></slot></div> `; }
ã·ã£ããŠDOMãé¢ä¿ããæåŸã®ã¿ãã³ãŒãã¯ããã«ãããŸããã¿ãã¯èŠçŽ å ã§ããŒã¯ã¢ãããåãå ¥ããããšãã§ããç¬èªã®ã¹ã¿ã€ã«ãå«ãããšãã§ããŸããã.renderïŒïŒã¡ãœããã¯é¢åã«ãªããŸããã ããã¯ããã³ãã¬ãŒãã®ä»æ§ãæ€èšãããšãã«æ¬¡åä¿®æ£ããäºå®ã§ãã
ã·ã£ããŠDOMãã䜿çšããããã«ã :: slottedïŒselectorïŒ pseudo-elementã䜿çšã§ããŸããããã¯ãã»ã¬ã¯ã¿ãŒã«äžèŽãããã¹ããããäžäœèŠçŽ ã®èŠçŽ ãéžæããå¿ èŠããããŸãã ã·ã£ããŠDOMã®ä»ã®CSSæ©èœã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã
ã€ãã³ãã«ã€ããŠ
ç§ã®ã¿ãã®äŸã¯ãããå®èšŒããæè¯ã®æ¹æ³ã§ã¯ãããŸããããã·ã£ããŠDOMã«ã¯ã€ãã³ãåäœæ©èœããããŸãã ãããã£ãŠãããšãã°ãããã¥ã¡ã³ãã«ãããšãåžžã«æãå åŽã®ã·ã£ããŠã«ãŒãã§åæ¢ããã€ãã³ãã®ãªã¹ãããããŸããäžæ¢ããšã©ãŒãéžæãå€æŽãããŒãããªã»ããããµã€ãºå€æŽãã¹ã¯ããŒã«ãselectstartã§ãã ã¯ãªãã¯ãdbclickãããã³ä»ã®ã»ãšãã©ãã¹ãŠã®ããŠã¹ã€ãã³ãããã€ãŒã«ããã©ãŒããã©ãŒã«ã¹ããã©ãŒã«ã¹ã€ã³ããã©ãŒã«ã¹ã¢ãŠããããŒããŠã³ãããŒã¢ããããã¹ãŠã®ãã©ãã°ã€ãã³ããããã³ãã®ä»ã®ããã€ãã¯ãã·ã£ããŠDOMããŒããŒãèªç±ã«è¶ããŸãã ç§ã¯ããã䜿çšããããšã¯ã§ããŸããã§ãããããã®æ å ±ã圹ç«ã€ãšæããŸãã
ãµããŒãã«ã€ããŠ
çŸåšãä»æ§ã®æåã®ããŒãžã§ã³ã®ãµããŒãã¯ã Chrome ã Opera ãéšåçã«Safariã§å®è£ ãããFirefoxã§å®è£ ãããŠããŸãã
ãã®ã·ãªãŒãºã®èšäºïŒ
æåã®èšäºïŒ Webã³ã³ããŒãã³ãã ããŒã1ïŒã«ã¹ã¿ã èŠçŽ
3çªç®ã®èšäºïŒ Webã³ã³ããŒãã³ãã ããŒã3ïŒHTMLãã³ãã¬ãŒããšã€ã³ããŒã
ãæž èŽããããšãããããŸãããå³ããå€æããªãã§ãã ããã ããããTania_N