初めての [Web Components]
2つのテンプレートを利用しています。
<!-- Mario$$.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Bulma Handlebars" />
<title>Bulma Project [Web Components]</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css"
/>
<script
defer
src="https://use.fontawesome.com/releases/v5.7.1/js/all.js"
></script>
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
<script src="../../js/shortBulma$$.js"></script>
<script src="../../js/shortHbs$$.js"></script>
<style>
body {
--theme-colour: var(--blue);
--background: #333;
background: var(--picker-colour);
--picker-colour: #777;
--blue: #29abe2;
display: flex;
height: 100%;
/* height: 100vh; */
font-family: sans-serif;
background-color: var(--background);
color: white;
}
twoot-post {
margin: auto;
}
</style>
<template id="twoot-post">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css" />
<style>
:host {
font-size: 24px;
font-family: inherit;
}
.reactions {
border-top: 2px solid var(--theme-colour);
border-bottom: 2px solid var(--theme-colour);
min-height: 50px;
padding: 0 0.5em;
}
</style>
<div class="columns is-mobile is-primary">
<div class="column is-2">
<div class="avatar"><img /></div>
</div>
<div class="column is-8">
<div class="content"><slot></slot></div>
</div>
<div class="column is-2 reaction">
<div class="reaction">
<reaction-picker></reaction-picker>
</div>
</div>
</div>
<div class="reactions pt-2"></div>
</template>
<template id="emoji-picker">
<style>
:host {
width: 100%;
height: 100%;
display: flex;
position: relative;
}
button {
border: none;
background: none;
color: var(--theme-colour);
font-size: 2em;
cursor: pointer;
}
button:active,
button:focus {
outline: inherit;
}
ul {
position: absolute;
border: 2px solid var(--theme-colour);
list-style: none;
padding: 0.4em;
left: -20%;
top: -103%;
background: var(--background);
}
ul.hidden {
display: none;
}
li button:hover,
li button:focus {
background: var(--picker-colour);
}
</style>
<button class="selected">+</button>
<ul class="hidden">
<li><button>😃</button></li>
<li><button>😞</button></li>
<li>
<button><small> </small>🚡</button>
</li>
</ul>
</template>
</head>
<body>
<section class="section">
<div class="container">
<div class="columns">
<div class="column"></div>
<div class="column is-10 mt-4">
<article class="message is-primary">
<div class="message-header subtitle">
<p>初めての [<strong>Web Components</strong>]</p>
</div>
<span class="message-body has-text-centered is-size-5">
<span class="is-size-5">2つのテンプレート</span>
</span>
</article>
<main>
<div class="columns is-centered mt-6">
<div class="column is-10">
<twoot-post avatar="../../img/bowser-avatar.png">
Hey Mario,<br />
the princess is in
<a href="https://goo.gl/maps/cZzyjm8LMrF2"
>another castle</a
>
</twoot-post>
</div>
</div>
<div class="columns is-centered mt-6">
<div class="column is-10">
<twoot-post avatar="../../img/Racoon_Mario_24649.png">
../../Racoon_Mario_24649.png,<br />
the princess is in another castle? Ok!
<a href="https://goo.gl/maps/cZzyjm8LMrF2"
>another castle</a
>
</twoot-post>
</div>
</div>
<div class="columns is-centered mt-6">
<div class="column is-10">
<twoot-post avatar="../../img/Goomba_24659.png">
Goomba_24659.png<br />
Hum Hum Hum ...
<a href="https://goo.gl/maps/cZzyjm8LMrF2"
>another castle</a
>
</twoot-post>
</div>
</div>
</main>
<div class="box mt-6">
<div class="box">
<h2 class="is-size-4 has-background-white-ter p-2 km"> 解説</h2>
<div class="content">
<ul>
<li class="pt-1">
<dl>
<dt>
<strong
>$$oa_t(this.shadowRoot, 'twoot-post');</strong
>
</dt>
<dd class="py-2">
テンプレート#templateをコンパイルし、コンテキストvを適用して得られたHTMLコードを、要素#contentsのinnserHTMLプロパティに代入する。
</dd>
<dt>
<strong
>$$oq(this.shadowRoot, 'img')</strong
>
</dt>
<dd class="py-2">
オブジェクトthis.shadowRootから'img'要素を求める。
</dd>
<dt>
<strong
>$$oe = (o, f, evNa = 'click')
</strong>
</dt>
<dd class="py-2">
オブジェクトthis.shadowRootに、clickイベントリスナーf を登録する。
</dd>
<dt>
<strong
>$$ocL(this.options, 'hidden', 'remove');</strong
>
</dt>
<dd class="py-2">
オブジェクトから'hidden'クラスを取り除く。
</dd>
</dl>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="column"></div>
</div>
</div>
</section>
<script>
customElements.define(
'twoot-post',
class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
$$oa_t(this.shadowRoot, 'twoot-post');
$$oq(this.shadowRoot, 'img').src = this.getAttribute('avatar');
this.reactionsElement = $$oq(this.shadowRoot, '.reactions');
this.reactions = [];
$$oe(
this.shadowRoot,
(event) => {
this.reactions.push(event.detail);
this.reactionsElement.textContent = this.reactions.join('');
},
'reaction-selected'
);
}
}
);
customElements.define(
'reaction-picker',
class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
$$oa_t(this.shadowRoot, 'emoji-picker');
this.selected = $$oq(this.shadowRoot, 'button.selected');
this.options = $$oq(this.shadowRoot, 'ul');
$$oe(this.selected, () => {
$$ocL(this.options, 'hidden', 'remove');
});
$$oe(this.options, (event) => {
this.value = event.target.textContent;
$$ocL(this.options, 'hidden', 'add');
});
}
toggleList() {
$$ocL(this.options, 'hidden');
}
set value(emoji) {
this._value = emoji;
this.selected.textContent = emoji;
this.dispatchEvent(
new CustomEvent('reaction-selected', {
detail: emoji,
bubbles: true,
})
);
}
get value() {
return this._value;
}
}
);
</script>
</body>
</html>例えば、notification$$.htmlとshortBulma$$.jsが同じフォルダにある時は
<script src="./shortBulma$$.js"></script> または
<script src="shortBulma$$.js"></script> となります。