mirror of
https://github.com/JeremyLikness/vanillajs-deck
synced 2024-12-04 19:27:37 +00:00
Add JSDoc comments
This commit is contained in:
parent
5b0c9fbc15
commit
5daad9fcaa
@ -1,11 +1,19 @@
|
|||||||
@keyframes slide-left {
|
@keyframes slide-left {
|
||||||
from { margin-left: 0vw; }
|
from {
|
||||||
to { margin-left: -100vw; }
|
margin-left: 0vw;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
margin-left: -100vw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes enter-right {
|
@keyframes enter-right {
|
||||||
from { margin-left: 100vw; }
|
from {
|
||||||
to { margin-left: 0vw; }
|
margin-left: 100vw;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
margin-left: 0vw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.anim-slide-left-begin {
|
.anim-slide-left-begin {
|
||||||
@ -21,8 +29,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
from { transform: rotate(0deg) }
|
from {
|
||||||
to { transform: rotate(360deg) }
|
transform: rotate(0deg)
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.anim-spin {
|
.anim-spin {
|
||||||
|
@ -1,18 +1,43 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles animations and transitions
|
||||||
|
* @property {boolean} _transitioning True when animation in effect
|
||||||
|
* @property {string} _begin The beginning animation class
|
||||||
|
* @property {string} _end The ending animation class
|
||||||
|
*/
|
||||||
export class Animator {
|
export class Animator {
|
||||||
|
/**
|
||||||
|
* Create an instance of the animation helper
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this._transitioning = false;
|
this._transitioning = false;
|
||||||
this._begin = null;
|
this._begin = null;
|
||||||
this._end = null;
|
this._end = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when animation in effect
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
get transitioning() {
|
get transitioning() {
|
||||||
return this._transitioning;
|
return this._transitioning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when ready to complete second part of animation
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
get animationReady() {
|
get animationReady() {
|
||||||
return !!this._end;
|
return !!this._end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kicks off a new animation (old slide)
|
||||||
|
* @param {string} animationName Name of the animation
|
||||||
|
* @param {HTMLDivElement} host The div to be animated
|
||||||
|
* @param {Function} callback Function to call when the animation completes
|
||||||
|
*/
|
||||||
beginAnimation(animationName, host, callback) {
|
beginAnimation(animationName, host, callback) {
|
||||||
this._transitioning = true;
|
this._transitioning = true;
|
||||||
this._begin = `anim-${animationName}-begin`;
|
this._begin = `anim-${animationName}-begin`;
|
||||||
@ -27,6 +52,10 @@ export class Animator {
|
|||||||
host.classList.add(this._begin);
|
host.classList.add(this._begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kicks off the final animation (new slide)
|
||||||
|
* @param {HTMLDivElement} host The div to animate
|
||||||
|
*/
|
||||||
endAnimation(host) {
|
endAnimation(host) {
|
||||||
this._transitioning = true;
|
this._transitioning = true;
|
||||||
const animationEnd = () => {
|
const animationEnd = () => {
|
||||||
|
@ -2,11 +2,13 @@ import { registerDeck } from "./navigator.js"
|
|||||||
import { registerControls } from "./controls.js"
|
import { registerControls } from "./controls.js"
|
||||||
import { registerKeyHandler } from "./keyhandler.js"
|
import { registerKeyHandler } from "./keyhandler.js"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main application element, simply registers the web components
|
||||||
|
*/
|
||||||
const app = async () => {
|
const app = async () => {
|
||||||
registerDeck();
|
registerDeck();
|
||||||
registerControls();
|
registerControls();
|
||||||
registerKeyHandler();
|
registerKeyHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", app);
|
document.addEventListener("DOMContentLoaded", app);
|
||||||
|
|
56
js/controls.js
vendored
56
js/controls.js
vendored
@ -1,11 +1,35 @@
|
|||||||
class Controls extends HTMLElement {
|
// @ts-check
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
export class Controls extends HTMLElement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of controls
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
/** @type {CustomRef} */
|
||||||
this._controlRef = null;
|
this._controlRef = null;
|
||||||
|
/** @type {Navigator} */
|
||||||
this._deck = null;
|
this._deck = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the element is inserted into the DOM. Used to fetch the template and wire into the related Navigator instance.
|
||||||
|
*/
|
||||||
async connectedCallback() {
|
async connectedCallback() {
|
||||||
const response = await fetch("/templates/controls.html");
|
const response = await fetch("/templates/controls.html");
|
||||||
const template = await response.text();
|
const template = await response.text();
|
||||||
@ -14,11 +38,11 @@ class Controls extends HTMLElement {
|
|||||||
host.innerHTML = template;
|
host.innerHTML = template;
|
||||||
this.appendChild(host);
|
this.appendChild(host);
|
||||||
this._controlRef = {
|
this._controlRef = {
|
||||||
first: document.getElementById("ctrlFirst"),
|
first: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlFirst")),
|
||||||
prev: document.getElementById("ctrlPrevious"),
|
prev: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlPrevious")),
|
||||||
next: document.getElementById("ctrlNext"),
|
next: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlNext")),
|
||||||
last: document.getElementById("ctrlLast"),
|
last: /** @type {HTMLButtonElement} **/(document.getElementById("ctrlLast")),
|
||||||
pos: document.getElementById("position")
|
pos: /** @type {HTMLSpanElement} **/(document.getElementById("position"))
|
||||||
};
|
};
|
||||||
this._controlRef.first.addEventListener("click", () => this._deck.jumpTo(0));
|
this._controlRef.first.addEventListener("click", () => this._deck.jumpTo(0));
|
||||||
this._controlRef.prev.addEventListener("click", () => this._deck.previous());
|
this._controlRef.prev.addEventListener("click", () => this._deck.previous());
|
||||||
@ -27,20 +51,33 @@ class Controls extends HTMLElement {
|
|||||||
this.refreshState();
|
this.refreshState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of attributes to watch
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return ["deck"];
|
return ["deck"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
async attributeChangedCallback(attrName, oldVal, newVal) {
|
async attributeChangedCallback(attrName, oldVal, newVal) {
|
||||||
if (attrName === "deck") {
|
if (attrName === "deck") {
|
||||||
if (oldVal !== newVal) {
|
if (oldVal !== newVal) {
|
||||||
this._deck = document.getElementById(newVal);
|
this._deck = /** @type {Navigator} */(document.getElementById(newVal));
|
||||||
this._deck.addEventListener("slideschanged", () => this.refreshState());
|
this._deck.addEventListener("slideschanged", () => this.refreshState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshState() {
|
/**
|
||||||
|
* Enables/disables buttons and updates position based on index in the deck
|
||||||
|
*/
|
||||||
|
refreshState() {
|
||||||
const next = this._deck.hasNext;
|
const next = this._deck.hasNext;
|
||||||
const prev = this._deck.hasPrevious;
|
const prev = this._deck.hasPrevious;
|
||||||
this._controlRef.first.disabled = !prev;
|
this._controlRef.first.disabled = !prev;
|
||||||
@ -51,4 +88,5 @@ class Controls extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Register the custom slide-controls element */
|
||||||
export const registerControls = () => customElements.define('slide-controls', Controls);
|
export const registerControls = () => customElements.define('slide-controls', Controls);
|
@ -1,4 +0,0 @@
|
|||||||
export async function getJson(path) {
|
|
||||||
const response = await fetch(path);
|
|
||||||
return await response.json();
|
|
||||||
};
|
|
@ -1,18 +1,42 @@
|
|||||||
class KeyHandler extends HTMLElement {
|
// @ts-check
|
||||||
|
|
||||||
|
import { Navigator } from "./navigator.js"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom element to handle key press
|
||||||
|
*/
|
||||||
|
export class KeyHandler extends HTMLElement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a key handler instance
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
/**
|
||||||
|
* The related Navigator element
|
||||||
|
* @type {Navigator}
|
||||||
|
*/
|
||||||
this._deck = null;
|
this._deck = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the attributes being watched
|
||||||
|
* @returns {string[]} The attributes to watch
|
||||||
|
*/
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return ["deck"];
|
return ["deck"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when attributes change
|
||||||
|
* @param {string} attrName The attribute that changed
|
||||||
|
* @param {string} oldVal The old value
|
||||||
|
* @param {string} newVal The new value
|
||||||
|
*/
|
||||||
async attributeChangedCallback(attrName, oldVal, newVal) {
|
async attributeChangedCallback(attrName, oldVal, newVal) {
|
||||||
if (attrName === "deck") {
|
if (attrName === "deck") {
|
||||||
if (oldVal !== newVal) {
|
if (oldVal !== newVal) {
|
||||||
this._deck = document.getElementById(newVal);
|
this._deck = /** @type {Navigator} */(document.getElementById(newVal));
|
||||||
this._deck.parentElement.addEventListener("keydown", key => {
|
this._deck.parentElement.addEventListener("keydown", key => {
|
||||||
if (key.keyCode == 39 || key.keyCode == 32) {
|
if (key.keyCode == 39 || key.keyCode == 32) {
|
||||||
this._deck.next();
|
this._deck.next();
|
||||||
@ -26,4 +50,7 @@ class KeyHandler extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the custom key-handler element
|
||||||
|
*/
|
||||||
export const registerKeyHandler = () => customElements.define('key-handler', KeyHandler);
|
export const registerKeyHandler = () => customElements.define('key-handler', KeyHandler);
|
@ -1,9 +1,22 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
import { loadSlides } from "./slideLoader.js"
|
import { loadSlides } from "./slideLoader.js"
|
||||||
|
import { Slide } from "./slide.js"
|
||||||
import { Router } from "./router.js"
|
import { Router } from "./router.js"
|
||||||
import { Animator } from "./animator.js"
|
import { Animator } from "./animator.js"
|
||||||
|
|
||||||
class Navigator extends HTMLElement {
|
/**
|
||||||
|
* The main class that handles rendering the slide decks
|
||||||
|
* @property {Animator} _animator Animation helper
|
||||||
|
* @property {Router} _router Routing helper
|
||||||
|
* @property {string} _route The current route
|
||||||
|
* @property {CustomEvent} slidesChangedEvent Event fired when slide changes
|
||||||
|
*/
|
||||||
|
export class Navigator extends HTMLElement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of the custom navigator element
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._animator = new Animator();
|
this._animator = new Animator();
|
||||||
@ -19,15 +32,25 @@ class Navigator extends HTMLElement {
|
|||||||
if (this._route) {
|
if (this._route) {
|
||||||
var slide = parseInt(this._route) - 1;
|
var slide = parseInt(this._route) - 1;
|
||||||
this.jumpTo(slide);
|
this.jumpTo(slide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of observed attributes
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return ["start"];
|
return ["start"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an attribute changes
|
||||||
|
* @param {string} attrName
|
||||||
|
* @param {string} oldVal
|
||||||
|
* @param {string} newVal
|
||||||
|
*/
|
||||||
async attributeChangedCallback(attrName, oldVal, newVal) {
|
async attributeChangedCallback(attrName, oldVal, newVal) {
|
||||||
if (attrName === "start") {
|
if (attrName === "start") {
|
||||||
if (oldVal !== newVal) {
|
if (oldVal !== newVal) {
|
||||||
@ -43,26 +66,50 @@ class Navigator extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current slide index
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
get currentIndex() {
|
get currentIndex() {
|
||||||
return this._currentIndex;
|
return this._currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current slide
|
||||||
|
* @returns {Slide}
|
||||||
|
*/
|
||||||
get currentSlide() {
|
get currentSlide() {
|
||||||
return this._slides ? this._slides[this._currentIndex] : null;
|
return this._slides ? this._slides[this._currentIndex] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total number of slides
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
get totalSlides() {
|
get totalSlides() {
|
||||||
return this._slides ? this._slides.length : 0;
|
return this._slides ? this._slides.length : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if a previous slide exists
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
get hasPrevious() {
|
get hasPrevious() {
|
||||||
return this._currentIndex > 0;
|
return this._currentIndex > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if a next slide exists
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
get hasNext() {
|
get hasNext() {
|
||||||
return this._currentIndex < (this.totalSlides - 1);
|
return this._currentIndex < (this.totalSlides - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main slide navigation: jump to specific slide
|
||||||
|
* @param {number} slideIdx
|
||||||
|
*/
|
||||||
jumpTo(slideIdx) {
|
jumpTo(slideIdx) {
|
||||||
if (this._animator.transitioning) {
|
if (this._animator.transitioning) {
|
||||||
return;
|
return;
|
||||||
@ -71,9 +118,9 @@ class Navigator extends HTMLElement {
|
|||||||
this._currentIndex = slideIdx;
|
this._currentIndex = slideIdx;
|
||||||
this.innerHTML = '';
|
this.innerHTML = '';
|
||||||
this.appendChild(this.currentSlide.html);
|
this.appendChild(this.currentSlide.html);
|
||||||
this._router.setRoute(slideIdx+1);
|
this._router.setRoute((slideIdx + 1).toString());
|
||||||
this._route = this._router.getRoute();
|
this._route = this._router.getRoute();
|
||||||
document.title = `${this.currentIndex+1}/${this.totalSlides}: ${this.currentSlide.title}`;
|
document.title = `${this.currentIndex + 1}/${this.totalSlides}: ${this.currentSlide.title}`;
|
||||||
this.dispatchEvent(this.slidesChangedEvent);
|
this.dispatchEvent(this.slidesChangedEvent);
|
||||||
if (this._animator.animationReady) {
|
if (this._animator.animationReady) {
|
||||||
this._animator.endAnimation(this.querySelector("div"));
|
this._animator.endAnimation(this.querySelector("div"));
|
||||||
@ -81,13 +128,16 @@ class Navigator extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advance to next slide, if it exists. Applies animation if transition is specified
|
||||||
|
*/
|
||||||
next() {
|
next() {
|
||||||
if (this.hasNext) {
|
if (this.hasNext) {
|
||||||
if (this.currentSlide.transition !== null) {
|
if (this.currentSlide.transition !== null) {
|
||||||
this._animator.beginAnimation(
|
this._animator.beginAnimation(
|
||||||
this.currentSlide.transition,
|
this.currentSlide.transition,
|
||||||
this.querySelector("div"),
|
this.querySelector("div"),
|
||||||
() => this.jumpTo(this.currentIndex+1));
|
() => this.jumpTo(this.currentIndex + 1));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.jumpTo(this.currentIndex + 1);
|
this.jumpTo(this.currentIndex + 1);
|
||||||
@ -95,6 +145,9 @@ class Navigator extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move to previous slide, if it exists
|
||||||
|
*/
|
||||||
previous() {
|
previous() {
|
||||||
if (this.hasPrevious) {
|
if (this.hasPrevious) {
|
||||||
this.jumpTo(this.currentIndex - 1);
|
this.jumpTo(this.currentIndex - 1);
|
||||||
@ -102,4 +155,7 @@ class Navigator extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the custom slide-deck component
|
||||||
|
*/
|
||||||
export const registerDeck = () => customElements.define('slide-deck', Navigator);
|
export const registerDeck = () => customElements.define('slide-deck', Navigator);
|
28
js/router.js
28
js/router.js
@ -1,11 +1,25 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles routing for the app
|
||||||
|
*/
|
||||||
export class Router {
|
export class Router {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
/**
|
||||||
|
* @property {HTMLDivElement} _eventSource Arbitrary DIV used to generate events
|
||||||
|
*/
|
||||||
this._eventSource = document.createElement("div");
|
this._eventSource = document.createElement("div");
|
||||||
|
/**
|
||||||
|
* @property {CustomEvent} _routeChanged Custom event raised when the route changes
|
||||||
|
*/
|
||||||
this._routeChanged = new CustomEvent("routechanged", {
|
this._routeChanged = new CustomEvent("routechanged", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
cancelable: false
|
cancelable: false
|
||||||
});
|
});
|
||||||
|
/**
|
||||||
|
* @property {string} _route The current route
|
||||||
|
*/
|
||||||
this._route = null;
|
this._route = null;
|
||||||
window.addEventListener("popstate", () => {
|
window.addEventListener("popstate", () => {
|
||||||
if (this.getRoute() !== this._route) {
|
if (this.getRoute() !== this._route) {
|
||||||
@ -15,15 +29,27 @@ export class Router {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the event source
|
||||||
|
* @returns {HTMLDivElement} The event source div
|
||||||
|
*/
|
||||||
get eventSource() {
|
get eventSource() {
|
||||||
return this._eventSource;
|
return this._eventSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current route
|
||||||
|
* @param {string} route The route name
|
||||||
|
*/
|
||||||
setRoute(route) {
|
setRoute(route) {
|
||||||
window.location.hash = route;
|
window.location.hash = route;
|
||||||
this._route = route;
|
this._route = route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current route
|
||||||
|
* @returns {string} The current route name
|
||||||
|
*/
|
||||||
getRoute() {
|
getRoute() {
|
||||||
return window.location.hash.substr(1).replace(/\//ig, "/");
|
return window.location.hash.substr(1).replace(/\//ig, "/");
|
||||||
}
|
}
|
||||||
|
33
js/slide.js
33
js/slide.js
@ -1,38 +1,65 @@
|
|||||||
|
// @ts-check
|
||||||
|
/** Represents a slide */
|
||||||
export class Slide {
|
export class Slide {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {string} text - The content of the slide
|
||||||
|
*/
|
||||||
constructor(text) {
|
constructor(text) {
|
||||||
|
/** @property {string} _text - internal text representation */
|
||||||
this._text = text;
|
this._text = text;
|
||||||
|
/** @property {HTMLDivElement} _html - host div */
|
||||||
this._html = document.createElement('div');
|
this._html = document.createElement('div');
|
||||||
this._html.innerHTML = text;
|
this._html.innerHTML = text;
|
||||||
|
/** @property {string} _title - title of the slide */
|
||||||
this._title = this._html.querySelectorAll("title")[0].innerText;
|
this._title = this._html.querySelectorAll("title")[0].innerText;
|
||||||
const transition = this._html.querySelectorAll("transition");
|
/** @type{NodeListOf<HTMLElement>} */
|
||||||
|
const transition = (this._html.querySelectorAll("transition"));
|
||||||
if (transition.length) {
|
if (transition.length) {
|
||||||
this._transition = transition[0].innerText;
|
this._transition = transition[0].innerText;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._transition = null;
|
this._transition = null;
|
||||||
}
|
}
|
||||||
|
/** @type{NodeListOf<HTMLElement>} */
|
||||||
const hasNext = this._html.querySelectorAll("nextslide");
|
const hasNext = this._html.querySelectorAll("nextslide");
|
||||||
if (hasNext.length > 0) {
|
if (hasNext.length > 0) {
|
||||||
this._nextSlideName = hasNext[0].innerText;
|
this._nextSlideName = hasNext[0].innerText;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._nextSlideName = null;
|
this._nextSlideName = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The slide transition
|
||||||
|
* @return{string} The transition name
|
||||||
|
*/
|
||||||
get transition() {
|
get transition() {
|
||||||
return this._transition;
|
return this._transition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The slide title
|
||||||
|
* @return{string} The slide title
|
||||||
|
*/
|
||||||
get title() {
|
get title() {
|
||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HTML DOM node for the slide
|
||||||
|
* @return{HTMLDivElement} The HTML content
|
||||||
|
*/
|
||||||
get html() {
|
get html() {
|
||||||
return this._html;
|
return this._html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the next slide (filename without the .html extension)
|
||||||
|
* @return{string} The name of the next slide
|
||||||
|
*/
|
||||||
get nextSlide() {
|
get nextSlide() {
|
||||||
return this._nextSlideName;
|
return this._nextSlideName;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
|
//@ts-check
|
||||||
import { Slide } from "./slide.js"
|
import { Slide } from "./slide.js"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a single slide
|
||||||
|
* @param {string} slideName The name of the slide
|
||||||
|
* @returns {Promise<Slide>} The slide
|
||||||
|
*/
|
||||||
async function loadSlide(slideName) {
|
async function loadSlide(slideName) {
|
||||||
const response = await fetch(`./slides/${slideName}.html`);
|
const response = await fetch(`./slides/${slideName}.html`);
|
||||||
const slide = await response.text();
|
const slide = await response.text();
|
||||||
return new Slide(slide);
|
return new Slide(slide);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} start The name of the slide to begin with
|
||||||
|
* @returns {Promise<Slide[]>} The array of loaded slides
|
||||||
|
*/
|
||||||
export async function loadSlides(start) {
|
export async function loadSlides(start) {
|
||||||
var next = start;
|
var next = start;
|
||||||
const slides = [];
|
const slides = [];
|
||||||
@ -20,6 +31,6 @@ export async function loadSlides(start) {
|
|||||||
else {
|
else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return slides;
|
return slides;
|
||||||
}
|
}
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Vanilla.js: Modern 1st Party JavaScript",
|
|
||||||
"start": "001-title"
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user