litespeed.js
Version:
Lite & fast micro javascript framework that is easy to learn
158 lines (133 loc) • 5.94 kB
JavaScript
window.ls.container.get('view').add({
selector: 'data-ls-bind',
controller: function(element, expression, container) {
let debug = element.getAttribute('data-debug') || false;
let echo = function(value, bind = true) {
if(
element.tagName === 'INPUT' ||
element.tagName === 'SELECT' ||
element.tagName === 'BUTTON' ||
element.tagName === 'TEXTAREA'
) {
let type = element.getAttribute('type');
if ('radio' === type) {
if (value.toString() === element.value) {
element.setAttribute('checked', 'checked');
}
else {
element.removeAttribute('checked');
}
if(bind) {
element.addEventListener('change', () => {
for(let i = 0; i < paths.length; i++) {
if(element.checked) {
value = element.value;
}
container.path(paths[i], value);
}
});
}
return;
}
if('checkbox' === type) {
if(typeof value === 'boolean' || value === 'true' || value === 'false') {
if(value === true || value === 'true') {
element.setAttribute('checked', 'checked');
element.checked = true;
}
else {
element.removeAttribute('checked');
element.checked = false;
}
}
else {
try {
value = JSON.parse(value);
element.checked = (Array.isArray(value) && (value.indexOf(element.value) > -1));
value = element.value;
}
catch {
return null;
}
}
if(bind) {
element.addEventListener('change', () => {
for(let i = 0; i < paths.length; i++) {
let value = container.path(paths[i]);
let index = value.indexOf(element.value);
if(element.checked && index < 0) {
value.push(element.value);
}
if(!element.checked && index > -1) {
value.splice(index, 1);
}
container.path(paths[i], value);
}
});
}
return;
}
if (element.value !== value) {
element.value = value;
element.dispatchEvent(new Event('change'));
}
if(bind) {
element.addEventListener('input', sync);
element.addEventListener('change', sync);
}
}
else {
if(element.textContent != value) {
element.textContent = value;
}
}
};
let sync = (() => {
return () => {
if(debug) {
console.info('debug-ls-bind', 'sync-path', paths);
console.info('debug-ls-bind', 'sync-syntax', syntax);
console.info('debug-ls-bind', 'sync-syntax-parsed', parsedSyntax);
console.info('debug-ls-bind', 'sync-value',element.value);
}
for(let i = 0; i < paths.length; i++) {
if('{{' + paths[i] + '}}' !== parsedSyntax) { // Sync only direct path
if(debug) {
console.info('debug-ls-bind', 'sync-skipped-path', paths[i]);
console.info('debug-ls-bind', 'sync-skipped-syntax', syntax);
console.info('debug-ls-bind', 'sync-skipped-syntax-parsed', parsedSyntax);
}
continue;
}
if(debug) {
console.info('debug-ls-bind', 'sync-loop-path', paths[i]);
console.info('debug-ls-bind', 'sync-loop-syntax', parsedSyntax);
}
container.path(paths[i], element.value);
}
}
})();
let syntax = element.getAttribute('data-ls-bind');
let parsedSyntax = container.scope(syntax);
let unsync = (!!element.getAttribute('data-unsync')) || false;
let result = expression.parse(syntax);
let paths = expression.getPaths();
echo(result, !unsync);
element.addEventListener('looped', function () { // Rebind after loop comp finish to render
echo(expression.parse(parsedSyntax), false);
});
for(let i = 0; i < paths.length; i++) {
let path = paths[i].split('.');
if(debug) {
console.info('debug-ls-bind', 'bind-path', path);
console.info('debug-ls-bind', 'bind-syntax', syntax);
}
while(path.length) {
container.bind(element, path.join('.'), () => {
echo(expression.parse(parsedSyntax), false);
});
path.pop();
}
}
}
});