123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
-
- // Cache DOM elements
- const inputElements = document.querySelectorAll('[data-model]');
- const boundElements = document.querySelectorAll('[data-bind]');
- const loopElements = document.querySelectorAll('[data-loop]');
- /* --- Bind element --- */
- function binder(data) {
- let scope = {}
- // Add data
- if (data) {
- for (const propName of Object.getOwnPropertyNames(data)) {
- scope[propName] = data[propName];
- setBindValue(propName, data[propName]);
- }
- }
- // Loop through input elements
- for (let el of inputElements) {
- if (el.type === 'text' || el.type === 'hidden') {
- // Get property name from each input with an attribute of 'mm-model'
- let propName = el.getAttribute('data-model');
- // Set property update logic
- setPropUpdateLogic(scope, propName);
- // Update bound scope property on input change
- scope[propName] = el.value;
- el.addEventListener('keyup', e => {
- scope[propName] = el.value;
- });
- }
- }
- return scope;
- };
- function setPropUpdateLogic(scope, prop) {
- if (!scope.hasOwnProperty(prop)) {
- let value;
- Object.defineProperty(scope, prop, {
- // Automatically update bound dom elements when a scope property is set to a new value
- set: (newValue) => {
- value = newValue;
- // Set input elements to new value
- for (let el of inputElements) {
- if (el.getAttribute('data-model') === prop) {
- if (el.type) {
- el.value = newValue;
- }
- }
- }
- // Set all other bound dom elements to new value
- setBindValue(prop, newValue);
- },
- get: () => {
- return value;
- },
- enumerable: true
- })
- }
- }
- function setBindValue(prop, newValue) {
- for (let el of boundElements) {
- if (el.getAttribute('data-bind') === prop) {
- if (!el.type) {
- el.innerHTML = newValue;
- }
- }
- }
- }
- /* --- For each --- */
- function looper(scope) {
- for (let el of loopElements) {
- let propName = el.getAttribute('data-loop');
- let data = scope[propName];
- let html = [];
- // If data is an array (if not do nothing)
- if (data && Array.isArray(data)) {
- // If data is already computed back to the initial value
- const defaultValue = el.querySelector('[data-looped]')
- if (defaultValue) {
- el.innerHTML = defaultValue.innerHTML;
- }
- // Add the not computed value
- html.push(`<div data-looped="${propName}" style="display: none">${el.innerHTML}</div>`);
- // Add info to replace value
- for (let i = 0; i < data.length; i++) {
- html.push(el.innerHTML.replace(/data-val="/g, 'data-index="' + i + '" data-val="'));
- }
- el.innerHTML = html.join("\n");
- // Replace value for the current loop
- const currentLoopElements = document.querySelectorAll('[data-loop=' + propName + ']');
- for (const currentElement of currentLoopElements) {
- valElements = currentElement.querySelectorAll('[data-val][data-index]');
- for (const valElement of valElements) {
- const val = scope[propName][valElement.getAttribute('data-index')][valElement.getAttribute('data-val')];
- if (val) {
- valElement.innerHTML = val;
- }
- }
- }
- }
- }
- }
|