frameworkless_finished

by cnhhoang850

HTML

<script src="https://jsfiddle.net/cnhhoang850/u23fcvbs"></script>
<script src="https://jsfiddle.net/cnhhoang850/w1ranuh7/"></script>
<script src="https://jsfiddle.net/cnhhoang850/erc39g5o"></script>
<script src="https://jsfiddle.net/cnhhoang850/La2t43ze/"></script>
<html>
    <body>
        <section class="app">
            <header class="header">
                <h1>Notes</h1>
                <input
                    type="text"
                    class="new_note"
                    placeholder="Input new note here"
                    autofocus=""
                />
            </header>
            <section class="main">
                <input type="checkbox" class="show-all" id="show-all" />
                <label for="show-all"> Show all notes </label>
                <ul class="todo-list" data-component="todo-list"></ul>
            </section>
            <footer class="footer">
                <span class="count" data-component="count">Count: </span>
                <ul class="filters" data-component="filter">
                    <li><a href="#/">All</a></li>
                    <li><a href="#/active">Active</a></li>
                    <li><a href="#/completed">Completed</a></li>
                </ul>
                <button class="clear-all">Clear completed</button>
            </footer>
        </section>
        <script type="module" src="index.js"></script>
    </body>
</html>

JavaScript

import renderer from "@jsfiddle/cnhhoang850/u23fcvbs.js";
import Todo from "@jsfiddle/cnhhoang850/w1ranuh7.js";
import Count from "@jsfiddle/cnhhoang850/erc39g5o.js";
import Filter from "@jsfiddle/cnhhoang850/La2t43ze.js";

renderer.add("todo-list", Todo);
renderer.add("count", Count);
renderer.add("filter", Filter);

const randomValues = ["note1", "note2", "note3", "note4", "note5", "note6"];

const state = {
  todos: [],
  filter: "All",
};

const render = () => {
  window.requestAnimationFrame(() => {
    const root = document.querySelector(".app");
    const virtualRoot = renderer.renderRoot(root, state);
    root.replaceWith(virtualRoot);
  });
};

window.setInterval(() => {
  state.todos = Array.from({
      length: Math.floor(Math.random() * randomValues.length)
    },
    () => {
      return {
        value: randomValues[Math.floor(Math.random() * randomValues.length)],
        done: [true, false][Math.floor(Math.random() * 2)],
      };
    },
  );
  console.log(state.todos);
  render();
}, 1000);

render();

/*
-----------------------------------------------------------------------
render.js

const renderer = {};

// Wrap component by HTML data-attributes
const add = (dataAttribute, component) => {
  renderer[dataAttribute] = componentWrapper(component);
};

// Call the component and pass the state to child components
function componentWrapper(component) {
  const boundedComponent = (target, state) => {
    // Apply changes to target DOM with component function
    const componentDOM = component(target, state);

    const childDOMs = componentDOM.querySelectorAll("[data-component]");
    console.log(childDOMs);

    for (let childNode of childDOMs) {
      // Dùng data-component trong DOM node để lookup component
      const componentName = childNode.dataset.component;

      const childComponent = renderer[componentName];
      if (!childComponent) {
        return;
      } else {
        childNode.replaceWith(childComponent(childNode, state));
     ...