<custom-menu>
Menu example - js.info
elem.classList (
DOMTokenList
) 👉 DOM Hierarchymethods:
add()
,remove()
,replace()
,toggle()
,contains()
...
/* ---------- helper methods ---------- */
// root.$()
DocumentFragment.prototype.$ = function(selector){
return this.querySelector(selector);
};
// ⭐️ get/set attribute
// get: elem.attr(name)
// set: elem.attr(name, value)
Element.prototype.attr = function(name, value=undefined){
if(value !== undefined){ this.setAttribute(name, value) };
return this.getAttribute(name) || undefined;
};
/* ---------- custom element ---------- */
class CustomMenu extends HTMLElement {
// connected to document
connectedCallback() {
// attach shadow root
let root = this.attachShadow({mode: 'open'});
// ⭐️ clone nodes from <template>
let clone = tmpl.content.cloneNode(true);
root.append( clone );
this.menu = root.$('.menu');
this.menuTitle = root.$('slot[name="title"]');
// we can't select light DOM nodes,
// so let's handle clicks on the slot
this.menuTitle.onclick = () => {
// open/close the menu
this.menu.classList.toggle('closed');
console.log(this.menu.classList);
};
}
}
customElements.define('custom-menu', CustomMenu);
<!-- custom element -->
<custom-menu>
<!-- ⭐️ <slot> contents from light DOM -->
<span slot="title">Candy menu</span>
<li slot="item">Lollipop</li>
<li slot="item">Fruit Toast</li>
<li slot="item">Cup Cake</li>
</custom-menu>
<!-- ⭐️ shadow DOM template for `custom-menu` -->
<template id="tmpl">
<style>
slot[name="title"] {
cursor: pointer;
}
/* ⭐️ highlight every slotted on hover */
::slotted(:hover) {
background-color: hsla(60, 90%, 50%, 0.8);
border: 1px dotted black;
padding: 2px 4px;
border-radius: 4px;
}
.menu.closed ul {
visibility: hidden;
}
</style>
<div class="menu">
<!-- ⭐️ named slots -->
<slot name="title"></slot>
<ul>
<slot name="item"></slot>
</ul>
</div>
</template>
Last updated