Skip to content

artydev/mvu

Repository files navigation

MVU

Based on DML, Morphdom and HTL

MVU tries to follow the Model View Update pattern. The idea is to make the view a function of the state only.

MVU can be used directly in the browser, and don't use any external framework, it's plain vanilla Javascript.

Here is an example , you can test it here ChooseColors

const { html, dom, udom, render, svg } = mvu.MVU;
const target = document.getElementById("app")
let state = {
    init: true,
    red: 255,
    green: 128,
    blue: 125
}
function Circle(state) {
    const strcolor = (state) => `rgb(${state.red},${state.green},${state.blue})`;
    let node = (
        svg`<svg width="100px" height="100px" fill=${strcolor(state)}>
          ${svg`<circle cx=50 cy=50 r=50></circle>`}
      </svg>`
    )
    return node
}
function Slider(color, state) {
    let slider = dom();
    let input = html`
      <div> 
          <div style="display:flex;align-items:center">
              <div  style="width:50px;text-align:right;margin-right:10px;">
                  ${color.charAt(0).toUpperCase()}
              </div>
              <div>
                  <input type="range" min="0" max="255" value=${state[color]}>
              </div>
               ${state[color]}
          </div>
      </div>`
    udom();
    input.oninput = function (e) {
        let value = e.target.value
        state[color] = value;
        update(state)
    }
    return slider
}
function Title () {
  let title = html`<h1>A Simple Colors Chooser</h1>`
  return title
}
function App(state) {
    let app = dom();
    html`
      ${Title()}
      <div class='color-chooser'>
        <div>${Circle(state)}</div>
          <div class="color-slider">
            <div>
              <div>${Slider("red", state)}</div>
              <div>${Slider("green", state)}</div>
              <div>${Slider("blue", state)}</div>
            </div>
          </div>
      </div>` 
    udom();
    return app
}
function update(state) {
    render(target, App(state))
}
update(state);

Here is the a more compact version : ChooseColors

const { html, dom, udom, render, svg, tags } = mvu.MVU;
const { div, input, span } = tags;

const mcircle = () => 
  div('', `width:40px;height:40px;background:red;border-radius:50%`);

const Slider = (min, max, value, libelle) => {
  let slider = dom ();
    span(libelle);
    let eltinput = input("", {type : "range", style:"display:block", max, min, value});
    let eltvalue = div(eltinput.value.toString()) 
  udom();
  slider.style.display = "flex";
  return {
      input : eltinput,
      value: eltvalue
  }
}

function setColor(elt, R, G, B){ 
  console.log(R.input.value)
  elt.style.backgroundColor = `rgb(${R.input.value},${G.input.value},${B.input.value})`
}; 

function App () {
  const app = dom ();
    const circle = mcircle ();
    const [R, G, B] = [
      Slider(0, 255, 128, "R"),  
      Slider(0, 255, 128,  "G"), 
      Slider(0, 255, 128, "B")
    ];
  udom();
  
  [R, G, B].forEach((slider) => {
    slider.input.oninput = () =>  {
      circle.style.backgroundColor = `rgb(${R.input.value},${G.input.value},${B.input.value})`;
      slider.value.innerText = slider.input.value 
    }
  });
  
  setColor(circle, R, G, B); 
  
  return app;
}

render(app, App());