class Buildoz extends HTMLElement { constructor(){ super() // always call super() first! this.attrs = {} } static get observedAttributes(){ //observable attributes triggering attributeChangedCallback // anything added here will be observed for all buildoz tags // in your child, add you local 'color' observable attr with : // return([...super.observedAttributes, 'color']) return([]) } static define(name, cls){ const tag = `bz-${name}` if(!customElements.get(tag)) { // no wild redefinition customElements.define(tag, cls) } return cls } connectedCallback(){ // added to the DOM this.classList.add('buildoz') } disconnectedCallback(){ // removed from the DOM } } class BZselect extends Buildoz { constructor(){ super() this.value = null this.open = false //defaults, can be changed by corresponding attributes this.attrs = { label: 'Select...', } } connectedCallback() { super.connectedCallback() this.button = document.createElement('button') this.button.textContent = this.attrs.label this.prepend(this.button) this.button.addEventListener('click', this.toggle.bind(this)) this.options = this.querySelectorAll('option') for(const opt of this.options){ opt.addEventListener('click',(evt) => { this.onOption(evt.target.value) }) } } static get observedAttributes(){ return([...super.observedAttributes, 'label']) } attributeChangedCallback(name, oldValue, newValue) { this.attrs[name] = newValue // on the fly changes here } toggle(){ for(const opt of this.options){ if(this.open) opt.classList.remove('open') else opt.classList.add('open') } this.open = !this.open } onOption(value){ this.value =value this.toggle() const opt = Array.from(this.options).find(opt => opt.value==value) this.button.textContent = opt.textContent } fill(opts){ this.el.innerHTML ='' if(!Array.isArray(opts)) opts = [opts] const ul = Object.assign(document.createElement('ul'), { className: `bz-selector ${this.config.ulClass ? this.config.ulClass :''}`, }) for(const opt of opts){ const li = document.createElement('li') li.innerHTML = `${opt.markup}` li.setAttribute('data-value', opt.value) ul.append(li) } this.el.append(ul) } } Buildoz.define('select', BZselect)