usakdsteen

ゆうさくですてぃーん

えいちてぃえむえる:かすたむ要素&てんぷれ要素

なんか知らんがオリジナルのタグを練成できるらしい…

 

developer.mozilla.org

 

オリジナルタグの名前はダッシュ記号を含む名前である必要があるみたいで

んでオリジナルタグはジャヴァスクリプト使って練成しなきゃならんらしい

 

このオリジナルタグ、VB6だとUserControlみたいな感じぽい?

内部パーツ構成とかそんな感じぽい

スタイルも内部で独自に持つ感じで

shadowDOMという機能で実現してるらしい・・・?

developer.mozilla.org

 

 

テンプレ要素

繰り返し使うようなパターンを再利用するための仕組みぽい?

これもジャヴァスクリプトから操作して使うぽい

developer.mozilla.org

 

 

 

 

 

 

お試した

f:id:neetsdkasu:20200803060414p:plain

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>test</title>
        <style>
ul { list-style: none; }
.softbutton {
    border: none; background-color: rgb(224,224,224); border-radius: 3px;
    cursor: pointer; font: unset; padding: 0px 0.2rem; color: darkgrey;
}
.softbutton:active { outline: 2px auto black; }
.softbutton:hover { color: black; }
.action { margin: 0px; margin-bottom: 0.5rem; }
.action > .softbutton { margin-right: 1rem; font-size: 0.8rem; }
.timeline .datetime { color: grey; font-size: 0.8em; }
.timeline ul > li { border-top: 1px solid lightgrey; }
        </style>
    </head>
    <body>
        <header>
            <button>create custom element "post-template"</button>
            <button>clone from template element with id="post-template"</button>
        </header>
        <main>
            <section class="timeline">
                <h5>timeline</h5>

                <template id="post-template">
                    <!-- templateのCSSは独立してるらしく、htmlのCSSが効かない… -->
                    <li>
                        <div class="datetime"><time><slot name="datetime"></slot></time></div>
                        <p class="text"><slot name="text"></slot></p>
                        <slot name="images"><div>IMAGES HERE</div></slot>
                        <div class="action">
                            <button class="softbutton">reply</button>
                            <button class="softbutton">memo</button>
                            <button class="softbutton">edit</button>
                            <button class="softbutton">del</button>
                        </div>
                        <ul>
                            <slot name="replies"></slot>
                        </ul>
                    </li>
                </template>

                <template id="post-template-with-css">
                    <style>
                        ul { list-style: none; }
                        .softbutton {
                            border: none; background-color: rgb(224,224,224); border-radius: 3px;
                            cursor: pointer; font: unset; padding: 0px 0.2rem; color: darkgrey;
                        }
                        .softbutton:active { outline: 2px auto black; }
                        .softbutton:hover { color: black; }
                        .action { margin: 0px; margin-bottom: 0.5rem; }
                        .action > .softbutton { margin-right: 1rem; font-size: 0.8rem; }
                        .timeline .datetime { color: grey; font-size: 0.8em; }
                        .timeline ul > li { border-top: 1px solid lightgrey; }
                        /* templateの外の影響受けないぽいので.timelineやulのCSSセレクタが無効に… */
                    </style>
                    <li>
                        <div class="datetime"><time><slot name="datetime"></slot></time></div>
                        <p class="text"><slot name="text"></slot></p>
                        <slot name="images"><div>IMAGES HERE</div></slot>
                        <div class="action">
                            <button class="softbutton">reply</button>
                            <button class="softbutton">memo</button>
                            <button class="softbutton">edit</button>
                            <button class="softbutton">del</button>
                        </div>
                        <ul>
                            <slot name="replies"></slot>
                        </ul>
                    </li>
                </template>

                <ul>
                    <post-template>
                        <span slot="datetime">2020-08-02 21:05:01</span>
                        <span slot="text">ほげほげ~</span>
                        <span slot="images" style="font-size: 0.5em">post-template</span>
                    </post-template>
                    <post-template>
                        <span slot="datetime">2020-08-02 20:11:34</span>
                        <span slot="text">マジ~?</span>
                        <span slot="images" style="font-size: 0.5em">post-template</span>
                        <post-template slot="replies">
                            <span slot="datetime">2020-08-02 23:33:25</span>
                            <span slot="text">マジ!</span>
                            <span slot="images" style="font-size: 0.5em">post-template</span>
                        </post-template>
                    </post-template>
                    <post-template-with-css>
                        <span slot="datetime">2020-08-01 10:05:01</span>
                        <span slot="text">りんく!</span>
                        <span slot="images" style="font-size: 0.5em">post-template-with-css</span>
                        <post-template-with-css slot="replies">
                            <span slot="datetime">2020-08-02 03:22:00</span>
                            <span slot="text">りんく!りんく!</span>
                            <span slot="images" style="font-size: 0.5em">post-template-with-css</span>
                        </post-template-with-css>
                    </post-template-with-css>
                    <post-template>
                        <span slot="datetime">2020-08-01 03:33:31</span>
                        <span slot="text">あれれ~?</span>
                        <span slot="images" style="font-size: 0.5em">post-template</span>
                    </post-template>
                </ul>
            </section>
        </main>

        <script>
customElements.define('post-template',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('post-template');
      let templateContent = template.content;

      const shadowRoot = this.attachShadow({mode: 'open'})
        .appendChild(templateContent.cloneNode(true));
  }
});
customElements.define('post-template-with-css',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('post-template-with-css');
      let templateContent = template.content;

      const shadowRoot = this.attachShadow({mode: 'open'})
        .appendChild(templateContent.cloneNode(true));
  }
});

document.querySelector('header > button:first-child')
.addEventListener('click', () => {
    const e = document.createElement('post-template');
    
    // template内のcssが使われる…
    
    const dt = e.appendChild(document.createElement('span'));
    dt.textContent = '2020-08-02 23:59:59';
    dt.slot = 'datetime';
    const tx = e.appendChild(document.createElement('span'));
    tx.textContent = 'This is Custom Element "post-template"';
    tx.slot = 'text';

    const span = e.appendChild(document.createElement('span'));
    span.textContent = 'dummy'; // slot以外のノードの追加は出来ない…

    alert(`[B] e: ${e}`); // OK (HTMLElement)
    alert(`[B] li: ${e.querySelector('li')}`); // null
    alert(`[B] .action: ${e.querySelector('.action')}`); // null
    alert(`[B] *[slot="text"]: ${e.querySelector('*[slot="text"]')}`); // OK

    const ul = document.querySelector('.timeline > ul');
    ul.insertBefore(e, ul.firstChild);

    alert(`[A] e: ${e}`); // OK (HTMLElement)
    alert(`[A] li: ${e.querySelector('li')}`); // null
    alert(`[A] .action: ${e.querySelector('.action')}`); // null
    alert(`[A] *[slot="text"]: ${e.querySelector('*[slot="text"]')}`); // OK
});

document.querySelector('header > button:last-child')
.addEventListener('click', () => {
    const template = document.getElementById('post-template');
    const templateContent = template.content;
    const clone = document.importNode(templateContent, true);
    
    // ノードツリーの"構造"のコピーなのでcssがhtmlのものが適用される

    clone.querySelector('time').textContent = '2020-08-02 11:57:57';
    clone.querySelector('p').textContent = 'This is Clone from template element (id="post-template")';

    const span = clone.appendChild(document.createElement('span'));
    span.style.fontWeight = 'bold';
    span.style.color = 'red';
    span.textContent = 'dummy';
    span.slot = 'images'; // slotタグは意味をなさない…

    alert(`[B] clone: ${clone}`); // OK (DocumentFragment)
    alert(`[B] li: ${clone.querySelector('li')}`); // OK
    alert(`[B] .action: ${clone.querySelector('.action')}`); // OK
    alert(`[B] *[slot="text"]: ${clone.querySelector('*[slot="text"]')}`); // null

    const ul = document.querySelector('.timeline > ul');
    ul.insertBefore(clone, ul.firstChild);

    alert(`[A] clone: ${clone}`); // OK (DocumentFragment)
    alert(`[A] li: ${clone.querySelector('li')}`); // null (move to html document (new owner))
    alert(`[A] .action: ${clone.querySelector('.action')}`); // null (move to html document (new owner))
    alert(`[A] *[slot="text"]: ${clone.querySelector('*[slot="text"]')}`); // null
});
        </script>
    </body>
</html>