mirror of
https://github.com/JeremyLikness/vanillajs-deck
synced 2024-12-04 19:27:37 +00:00
Refactor data-binding to own class
This commit is contained in:
parent
0cab33efe5
commit
47a3dc8ba5
50
js/dataBinding.js
Normal file
50
js/dataBinding.js
Normal file
@ -0,0 +1,50 @@
|
||||
// @ts-check
|
||||
|
||||
export class DataBinding {
|
||||
|
||||
/**
|
||||
* Simple evaluation
|
||||
* @param {string} js The JavaScript to evaluate
|
||||
*/
|
||||
execute(js) {
|
||||
return eval(js);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates JavaScript with a constrained context (scope)
|
||||
* @param {string} src The JavaScript to evaluate
|
||||
* @param {object} context The context (data) to evaluate with
|
||||
* @returns {object} The result of the evaluation
|
||||
*/
|
||||
executeInContext(src, context) {
|
||||
return this.execute.call(context, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for "repeat" attribute to data-bind lists
|
||||
* @param {HTMLElement} elem The parent element to search
|
||||
* @param {object} context The context to use for binding
|
||||
*/
|
||||
bindLists(elem, context) {
|
||||
const listBinding = elem.querySelectorAll("[repeat]");
|
||||
listBinding.forEach(elem => {
|
||||
const parent = elem.parentElement;
|
||||
const expression = elem.getAttribute("repeat");
|
||||
elem.removeAttribute("repeat");
|
||||
const template = elem.outerHTML;
|
||||
parent.removeChild(elem);
|
||||
context[expression].forEach(item => {
|
||||
let newTemplate = `${template}`;
|
||||
const matches = newTemplate.match(/\{\{([^\}]*?)\}\}/g);
|
||||
if (matches) {
|
||||
matches.forEach(match => {
|
||||
match = match.replace("{{", "").replace("}}", "");
|
||||
const value = this.executeInContext(`this.${match}`, {item});
|
||||
newTemplate = newTemplate.replace(`{{${match}}}`, value);
|
||||
});
|
||||
parent.innerHTML += newTemplate;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
42
js/slide.js
42
js/slide.js
@ -1,4 +1,7 @@
|
||||
// @ts-check
|
||||
|
||||
import {DataBinding} from "./dataBinding.js"
|
||||
|
||||
/**
|
||||
* Represents a slide
|
||||
* */
|
||||
@ -19,6 +22,11 @@ export class Slide {
|
||||
* @type {object}
|
||||
*/
|
||||
this._context = {};
|
||||
/**
|
||||
* Data binding helper
|
||||
* @type {DataBinding}
|
||||
*/
|
||||
this._dataBinding = new DataBinding();
|
||||
/**
|
||||
* The HTML DOM hosting the slide contents
|
||||
* @type {HTMLDivElement}
|
||||
@ -57,41 +65,11 @@ export class Slide {
|
||||
// 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();
|
||||
this._dataBinding.executeInContext(script.innerText, this._context);
|
||||
this._dataBinding.bindLists(this._html, this._context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The slide transition
|
||||
* @returns {string} The transition name
|
||||
|
Loading…
Reference in New Issue
Block a user