initial commit
This commit is contained in:
commit
9fd405d39a
|
@ -0,0 +1,3 @@
|
||||||
|
# Alps
|
||||||
|
|
||||||
|
A Alpine Inspired Framework Learning Experiment
|
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
function saferEval(expression, dataContext, additionalHelperVariables = {}) {
|
||||||
|
return (new Function(['$data', ...Object.keys(additionalHelperVariables)], `var result; with($data) { result = ${expression} }; return result`))(
|
||||||
|
dataContext, ...Object.values(additionalHelperVariables)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Alps = {
|
||||||
|
directives: {
|
||||||
|
'x-text': (el, value) => {
|
||||||
|
el.innerText = value;
|
||||||
|
},
|
||||||
|
'x-show': (el, value) => {
|
||||||
|
el.style.display = value ? 'block' : 'none';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
start() {
|
||||||
|
// root scope
|
||||||
|
this.root = document.querySelector('[x-data]');
|
||||||
|
|
||||||
|
// initialize proxy data
|
||||||
|
this.data = this.initialize();
|
||||||
|
|
||||||
|
// add event listeners
|
||||||
|
this.registerListeners();
|
||||||
|
|
||||||
|
// refresh dom
|
||||||
|
this.refresh();
|
||||||
|
},
|
||||||
|
observe(data) {
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
return new Proxy(data, {
|
||||||
|
set(target, key, value) {
|
||||||
|
target[key] = value;
|
||||||
|
|
||||||
|
self.refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refresh() {
|
||||||
|
// dom tree walker
|
||||||
|
this.walkDom(this.root, (el) => {
|
||||||
|
// loop through attributes and look for directives
|
||||||
|
Array.from(el.attributes).forEach((attribute) => {
|
||||||
|
if(!Object.keys(this.directives).includes(attribute.name)) return;
|
||||||
|
|
||||||
|
this.directives[attribute.name](el, eval(`with (this.data) {(${attribute.value})}`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
registerListeners() {
|
||||||
|
this.walkDom(this.root, (el) => {
|
||||||
|
// loop through attributes and look for events
|
||||||
|
Array.from(el.attributes).forEach((attribute) => {
|
||||||
|
// exit early (only events here)
|
||||||
|
if(!attribute.name.startsWith('@')) return;
|
||||||
|
|
||||||
|
// find event
|
||||||
|
let event = attribute.name.replace('@', '');
|
||||||
|
|
||||||
|
// register event
|
||||||
|
el.addEventListener((event), () => {
|
||||||
|
eval(`with (this.data) {(${attribute.value})}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
initialize() {
|
||||||
|
// root scope data on x-data
|
||||||
|
let raw = this.root.getAttribute('x-data');
|
||||||
|
|
||||||
|
// eval that
|
||||||
|
return this.observe(eval(`(${raw})`));
|
||||||
|
},
|
||||||
|
walkDom(el, callback) {
|
||||||
|
// root element
|
||||||
|
callback(el);
|
||||||
|
|
||||||
|
// roots child
|
||||||
|
el = el.firstElementChild;
|
||||||
|
|
||||||
|
while(el) {
|
||||||
|
// get all the children's children
|
||||||
|
this.walkDom(el, callback);
|
||||||
|
|
||||||
|
// next
|
||||||
|
el = el.nextElementSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue