Very nice. I took a slight peek while ironing out the creases in mine.
I haven't quite figured out the next tweak where I want to convert
the value to/from a string by doing a map/reverse-map through the
label strings. Like, if this "clickbox" is a cell in a table I want to easily
convert the table contents to/from a CSV text file. And for this type of
cell it should read and write the unicode checkmark character and
internally recognize/store the value as "checkmark".
click.html:
<html>
<body>
<click-box cycle
states="empty checkmark xmark questionmark"
empty=""
checkmark="✓"
xmark="✖"
questionmark="?"></click-box>
</body>
<script src="click.js"></script>
</html>
click.js:
const clickBoxTemplate = document.createElement( "template" );
clickBoxTemplate.innerHTML = `
<style>
input{
text-align: center;
cursor: default;
}
</style>
<input id="box" type="text" readonly>
`;
function max( x, y ){
return y > x ? y : x;
}
class ClickBox extends HTMLElement {
constructor() {
super();
this.attachShadow( {mode:"open"} );
this.shadowRoot.appendChild( clickBoxTemplate.content.cloneNode(true) );
if( this.hasAttribute( "cycle" ) ){
this._states =
( this.hasAttribute("states") ?
this.getAttribute("states") : "empty true false" ).split( " " );
console.log( this._states );
this._stateNumber = 0;
this._state = this._states[ this._stateNumber ];
let box = this.shadowRoot.querySelector("#box");
let size = this._states.
map(x=>this.hasAttribute(x)?this.getAttribute(x):x).
map(x=>x.length).
reduce( max );
console.log( size );
box.setAttribute( "size", size );
}
}
increment() {
this._stateNumber = (this._stateNumber + 1) % this._states.length;
this._state = this._states[ this._stateNumber ];
}
draw() {
let box = this.shadowRoot.querySelector("#box");
console.log( box );
this.value = this._state;
console.log( this.value );
box.toggleAttribute( "readonly" );
if( this.hasAttribute( this.value ) ){
box.value = this.getAttribute( this.value );
} else {
box.value = this.value;
}
box.toggleAttribute( "readonly" );
box.blur();
}
click( event ){
event.preventDefault();
this.increment();
this.draw();
return;
}
connectedCallback() {
this.shadowRoot.querySelector("#box").addEventListener( "click", (e)=>this.click(e) );
}
disconnectedCallback() {
this.shadowRoot.querySelector("#box").removeEventListener();
}
}
window.customElements.define( "click-box", ClickBox );