ndf-elements
Version:
My collection of useful custom elements.
106 lines (80 loc) • 2.66 kB
JavaScript
/**
* A keyboard-accessible interactive to give a star rating.
*
* @copyright © Nick Freear, 04-Dec-2021.
*
* @WAS MyRadioStarRatingElement.
* @see ../demo/my-star-rating.html
* @status beta
* @since 1.0.0
*/
import { MyElement } from '../MyElement.js';
export class MyStarRatingElement extends MyElement { // HTMLInputElement {
static getTag () {
return 'my-star-rating';
}
get events () {
return [
{ sel: 'fieldset', name: 'click', fn: '_clickEventHandler' },
{ sel: 'fieldset', name: 'mouseout', fn: '_unfocusStars' }
];
}
async connectedCallback () {
const name = this.getAttribute('name') || 'my-star-rating-1';
await this._initialize({ name });
}
async _initialize (attr) {
const templates = await this.getTemplate('my-star-rating');
const labels = this.shadowRoot.querySelectorAll('label');
const hiddenInput = this._createHiddenInput(attr.name);
this.after(hiddenInput);
this.$$ = { ...attr, hiddenInput, labels, templates };
this._appendStars(labels, templates[1]);
this._addEventHandlers();
console.debug('my-star-rating (radio):', this.$$, this);
}
_createHiddenInput (name) {
const INPUT = document.createElement('input');
INPUT.id = 'my-star-rating-input-1';
INPUT.type = 'hidden';
INPUT.name = name;
// INPUT.value = 0;
// INPUT.setAttribute('data-stars', '0');
return INPUT;
}
_appendStars (labels, starSvgTemplate) {
// const starSvgTemplate = templates[ 1 ];
[...labels].forEach(label => {
const starSvg = starSvgTemplate.content.cloneNode(true);
label.appendChild(starSvg);
});
}
_updateValue (value) {
this.title = `${value} stars`;
this.setAttribute('data-value', value);
// this.$$.hiddenInput.setAttribute('data-value', value);
this.$$.hiddenInput.value = value;
}
_unfocusStars () {
[...this.$$.labels].map(label => label.classList.remove('focused'));
}
_updateState (VALUE) {
[...this.$$.labels].forEach((label, idx) => {
label.setAttribute('data-star', idx < VALUE ? 'yes' : 'no');
});
}
_clickEventHandler (ev) {
const LABEL = ev.target.parentElement;
const VALUE = parseInt(ev.target.value); // Was: ev.target.getAttribute('data-rating'));
if (ev.target.nodeName !== 'INPUT') { // NaN.
this._unfocusStars();
return;
}
this._updateValue(VALUE);
this._updateState(VALUE);
this._unfocusStars();
LABEL.classList.add('focused');
console.debug('Star rating. Click:', VALUE, VALUE ? 'ok' : 'err', ev);
}
}
// Was: MyStarRatingElement.define(); //, { extends: 'input' });