initial commit

This commit is contained in:
Geoff Doty 2024-06-15 13:57:04 -04:00
commit 9fd405d39a
2 changed files with 94 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Alps
A Alpine Inspired Framework Learning Experiment

91
src/alp.js Normal file
View File

@ -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;
}
}
}