vanillajs-deck/js/controls.js

102 lines
3.8 KiB
JavaScript
Raw Permalink Normal View History

2019-11-24 00:02:31 +00:00
// @ts-check
2019-11-23 00:37:45 +00:00
2019-11-24 00:02:31 +00:00
import { Navigator } from "./navigator.js"
/**
* @typedef {object} CustomRef
* @property {HTMLButtonElement} first The button to jump to the first slide
* @property {HTMLButtonElement} prev The button to move to the previous slide
* @property {HTMLButtonElement} next The button to advance to the next slide
* @property {HTMLButtonElement} last The button to advance to the last slide
* @property {HTMLSpanElement} pos The span for the positional information
*/
/**
* Custom element that renders controls to navigate the deck
2019-11-25 19:34:32 +00:00
* @extends {HTMLElement}
2019-11-24 00:02:31 +00:00
*/
export class Controls extends HTMLElement {
/**
* Create a new instance of controls
*/
2019-11-23 00:37:45 +00:00
constructor() {
super();
2019-11-25 19:34:32 +00:00
/**
* The internal reference list of controls
* @type {CustomRef}
*/
2019-11-23 00:37:45 +00:00
this._controlRef = null;
2019-11-25 19:34:32 +00:00
/**
* The related Navigator instance (deck) to control
* @type {Navigator}
*/
2019-11-23 00:37:45 +00:00
this._deck = null;
}
2019-11-24 00:02:31 +00:00
/**
* Called when the element is inserted into the DOM. Used to fetch the template and wire into the related Navigator instance.
*/
2019-11-23 00:37:45 +00:00
async connectedCallback() {
2020-01-29 22:03:43 +00:00
const response = await fetch("./templates/controls.html");
2019-11-23 00:37:45 +00:00
const template = await response.text();
this.innerHTML = "";
const host = document.createElement("div");
host.innerHTML = template;
this.appendChild(host);
this._controlRef = {
2019-11-24 00:02:31 +00:00
first: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlFirst")),
prev: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlPrevious")),
next: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlNext")),
last: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlLast")),
pos: /** @type {HTMLSpanElement} **/(document.getElementById("position"))
2019-11-23 00:37:45 +00:00
};
this._controlRef.first.addEventListener("click", () => this._deck.jumpTo(0));
this._controlRef.prev.addEventListener("click", () => this._deck.previous());
this._controlRef.next.addEventListener("click", () => this._deck.next());
this._controlRef.last.addEventListener("click", () => this._deck.jumpTo(this._deck.totalSlides - 1));
this.refreshState();
}
2019-11-24 00:02:31 +00:00
/**
* Get the list of attributes to watch
2019-11-25 19:34:32 +00:00
* @returns {string[]} List of observable attributes
2019-11-24 00:02:31 +00:00
*/
2019-11-23 00:37:45 +00:00
static get observedAttributes() {
return ["deck"];
}
2019-11-24 00:02:31 +00:00
/**
* Called when the attribute is set
* @param {string} attrName Name of the attribute that was set
* @param {string} oldVal The old attribute value
* @param {string} newVal The new attribute value
*/
2019-11-23 00:37:45 +00:00
async attributeChangedCallback(attrName, oldVal, newVal) {
if (attrName === "deck") {
if (oldVal !== newVal) {
2019-11-24 00:02:31 +00:00
this._deck = /** @type {Navigator} */(document.getElementById(newVal));
this._deck.addEventListener("slideschanged", () => this.refreshState());
2019-11-23 00:37:45 +00:00
}
}
}
2019-11-24 00:02:31 +00:00
/**
* Enables/disables buttons and updates position based on index in the deck
*/
refreshState() {
2019-11-26 00:46:59 +00:00
if (this._controlRef == null) {
return;
}
2019-11-23 00:37:45 +00:00
const next = this._deck.hasNext;
const prev = this._deck.hasPrevious;
this._controlRef.first.disabled = !prev;
this._controlRef.prev.disabled = !prev;
this._controlRef.next.disabled = !next;
2019-11-26 17:51:45 +00:00
this._controlRef.last.disabled = this._deck.currentIndex === (this._deck.totalSlides - 1);
2019-11-23 00:37:45 +00:00
this._controlRef.pos.innerText = `${this._deck.currentIndex + 1} / ${this._deck.totalSlides}`;
}
}
2019-11-24 00:02:31 +00:00
/** Register the custom slide-controls element */
2019-11-23 00:37:45 +00:00
export const registerControls = () => customElements.define('slide-controls', Controls);