vanillajs-deck/js/slide.js

126 lines
3.6 KiB
JavaScript
Raw Normal View History

2019-11-24 00:02:31 +00:00
// @ts-check
2019-11-25 19:34:32 +00:00
/**
* Represents a slide
* */
2019-11-22 19:28:19 +00:00
export class Slide {
2019-11-24 00:02:31 +00:00
/**
* @constructor
* @param {string} text - The content of the slide
*/
2019-11-22 19:28:19 +00:00
constructor(text) {
2019-11-25 19:34:32 +00:00
/**
* Internal text representation of the slide
* @type {string}
*/
2019-11-22 19:28:19 +00:00
this._text = text;
2019-11-26 00:46:59 +00:00
/**
* Context for embedded scripts
* @type {object}
*/
this._context = {};
2019-11-25 19:34:32 +00:00
/**
* The HTML DOM hosting the slide contents
* @type {HTMLDivElement}
*/
2019-11-22 19:28:19 +00:00
this._html = document.createElement('div');
this._html.innerHTML = text;
2019-11-25 19:34:32 +00:00
/**
* The title of the slide
* @type {string}
*/
2019-11-22 19:28:19 +00:00
this._title = this._html.querySelectorAll("title")[0].innerText;
2019-11-24 00:02:31 +00:00
/** @type{NodeListOf<HTMLElement>} */
const transition = (this._html.querySelectorAll("transition"));
2019-11-23 20:07:22 +00:00
if (transition.length) {
2019-11-25 19:34:32 +00:00
/**
* The name of the animation to use for transitions
* @type {string}
*/
2019-11-23 20:07:22 +00:00
this._transition = transition[0].innerText;
}
else {
this._transition = null;
}
2019-11-24 00:02:31 +00:00
/** @type{NodeListOf<HTMLElement>} */
2019-11-22 19:28:19 +00:00
const hasNext = this._html.querySelectorAll("nextslide");
if (hasNext.length > 0) {
2019-11-25 19:34:32 +00:00
/**
* The name of the next slide to load
* @type {string}
*/
2019-11-22 19:28:19 +00:00
this._nextSlideName = hasNext[0].innerText;
2019-11-24 00:02:31 +00:00
}
2019-11-22 19:28:19 +00:00
else {
this._nextSlideName = null;
2019-11-24 00:02:31 +00:00
}
2019-11-26 00:46:59 +00:00
// execute any scripts
const script = this._html.querySelector("script");
if (script) {
(function (/** @type {string} */src) {
return eval(src)
}).call(this._context, script.innerText);
this.dataBind();
}
}
/**
* Scans for data-binding and applies the bindings
*/
dataBind() {
const listBinding = this._html.querySelectorAll("[repeat]");
listBinding.forEach(elem => {
const parent = elem.parentElement;
const expression = elem.getAttribute("repeat");
elem.removeAttribute("repeat");
const template = elem.outerHTML;
parent.removeChild(elem);
this._context[expression].forEach(item => {
let newTemplate = `${template}`;
const matches = newTemplate.match(/\{\{([^\}]*?)\}\}/g);
if (matches) {
matches.forEach(match => {
match = match.replace("{{", "").replace("}}", "");
const value = (function (/** @type {string} */src) {
return eval(src)
}).call({ item }, match);
newTemplate = newTemplate.replace(`{{${match}}}`, value);
});
parent.innerHTML += newTemplate;
}
});
});
2019-11-22 19:28:19 +00:00
}
2019-11-24 00:02:31 +00:00
/**
* The slide transition
2019-11-25 19:34:32 +00:00
* @returns {string} The transition name
2019-11-24 00:02:31 +00:00
*/
2019-11-23 20:07:22 +00:00
get transition() {
return this._transition;
}
2019-11-24 00:02:31 +00:00
/**
* The slide title
2019-11-25 19:34:32 +00:00
* @returns {string} The slide title
2019-11-24 00:02:31 +00:00
*/
2019-11-22 19:28:19 +00:00
get title() {
return this._title;
}
2019-11-24 00:02:31 +00:00
/**
* The HTML DOM node for the slide
2019-11-25 19:34:32 +00:00
* @returns {HTMLDivElement} The HTML content
2019-11-24 00:02:31 +00:00
*/
2019-11-22 19:28:19 +00:00
get html() {
return this._html;
}
2019-11-24 00:02:31 +00:00
/**
* The name of the next slide (filename without the .html extension)
2019-11-25 19:34:32 +00:00
* @returns {string} The name of the next slide
2019-11-24 00:02:31 +00:00
*/
2019-11-22 19:28:19 +00:00
get nextSlide() {
return this._nextSlideName;
}
}