128 lines
3.9 KiB
JavaScript
128 lines
3.9 KiB
JavaScript
// GridSelector component definition
|
|
// This file should be loaded as a module (type="module") after the
|
|
// corresponding HTML template (grid-selector.html) is present in the DOM.
|
|
|
|
class GridSelector extends HTMLElement {
|
|
static get observedAttributes() {
|
|
return ['grid-color', 'grid-size', 'grid-numbering'];
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
// Attach a shadow root
|
|
this.attachShadow({ mode: 'open' });
|
|
|
|
// Load the template defined in grid-selector.html
|
|
const tmpl = document.getElementById('grid-selector-template');
|
|
if (!tmpl) {
|
|
console.error('GridSelector: template not found in DOM');
|
|
return;
|
|
}
|
|
this.shadowRoot.appendChild(tmpl.content.cloneNode(true));
|
|
|
|
// Grab elements from the template
|
|
this._colorInput = this.shadowRoot.querySelector('#grid-color');
|
|
this._sizeInput = this.shadowRoot.querySelector('#grid-size');
|
|
this._numberingInput = this.shadowRoot.querySelector('#grid-numbering');
|
|
|
|
// Bind event handlers
|
|
this._onColorChange = this._onColorChange.bind(this);
|
|
this._onSizeChange = this._onSizeChange.bind(this);
|
|
this._onNumberingChange = this._onNumberingChange.bind(this);
|
|
}
|
|
|
|
connectedCallback() {
|
|
// Initialise values from attributes or defaults
|
|
this._colorInput.value = this.getAttribute('grid-color') || '#000000';
|
|
this._sizeInput.value = this.getAttribute('grid-size') || '25';
|
|
const numbering = this.hasAttribute('grid-numbering')
|
|
? this.getAttribute('grid-numbering') === 'true'
|
|
: true;
|
|
this._numberingInput.checked = numbering;
|
|
|
|
// Register listeners
|
|
this._colorInput.addEventListener('input', this._onColorChange);
|
|
this._sizeInput.addEventListener('input', this._onSizeChange);
|
|
this._numberingInput.addEventListener('change', this._onNumberingChange);
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
this._colorInput.removeEventListener('input', this._onColorChange);
|
|
this._sizeInput.removeEventListener('input', this._onSizeChange);
|
|
this._numberingInput.removeEventListener('change', this._onNumberingChange);
|
|
}
|
|
|
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
if (oldValue === newValue) return;
|
|
switch (name) {
|
|
case 'grid-color':
|
|
if (this._colorInput) this._colorInput.value = newValue;
|
|
break;
|
|
case 'grid-size':
|
|
if (this._sizeInput) this._sizeInput.value = newValue;
|
|
break;
|
|
case 'grid-numbering':
|
|
if (this._numberingInput) this._numberingInput.checked = newValue === 'true';
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ----- Property getters / setters -----
|
|
get gridColor() {
|
|
return this._colorInput ? this._colorInput.value : this.getAttribute('grid-color');
|
|
}
|
|
set gridColor(v) {
|
|
this.setAttribute('grid-color', v);
|
|
}
|
|
|
|
get gridSize() {
|
|
return this._sizeInput ? Number(this._sizeInput.value) : Number(this.getAttribute('grid-size'));
|
|
}
|
|
set gridSize(v) {
|
|
this.setAttribute('grid-size', v);
|
|
}
|
|
|
|
get gridNumbering() {
|
|
return this._numberingInput ? this._numberingInput.checked : this.hasAttribute('grid-numbering') && this.getAttribute('grid-numbering') === 'true';
|
|
}
|
|
set gridNumbering(v) {
|
|
this.setAttribute('grid-numbering', v);
|
|
}
|
|
|
|
// ----- Internal event handlers -----
|
|
_onColorChange(e) {
|
|
const color = e.target.value;
|
|
this.setAttribute('grid-color', color);
|
|
this._dispatchChange();
|
|
}
|
|
|
|
_onSizeChange(e) {
|
|
const size = e.target.value;
|
|
this.setAttribute('grid-size', size);
|
|
this._dispatchChange();
|
|
}
|
|
|
|
_onNumberingChange(e) {
|
|
const checked = e.target.checked;
|
|
this.setAttribute('grid-numbering', checked);
|
|
this._dispatchChange();
|
|
}
|
|
|
|
_dispatchChange() {
|
|
this.dispatchEvent(
|
|
new CustomEvent('gridchange', {
|
|
detail: {
|
|
color: this.gridColor,
|
|
size: this.gridSize,
|
|
numbering: this.gridNumbering,
|
|
},
|
|
bubbles: true,
|
|
composed: true,
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
// Register the custom element
|
|
customElements.define('grid-selector', GridSelector);
|