DEV Community

artydev
artydev

Posted on

A Color Chooser in 64 lines of JS with MVU

Choose your favorite library and challenge this one :-)

This is an upgraded version of MVU (v2.0.3)

See how easy it is to handle SVG elements...thanks to htl

You can test it here ColorChooser

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);
Enter fullscreen mode Exit fullscreen mode

Top comments (8)

Collapse
 
efpage profile image
Eckehard • Edited

Hy artydev,

Nice to see that you can use these kind of "generative" functions (like "Slider") with all the advantages of local variables in HTML. No need to use ID´s anymore. Brilliant!

Just: with DML you could get the same result in less than 20 lines. This is just "event driven" DOM handling, but I cannot see any drawbacks. Maybe one advantage: You can put the DML-code in a function or a class and get something like a "component". It is fully self contained and does not need any redraw logic. How do you manage this in MVU?

As far as I understood, MVU relies on morphdom, which could be a great option if you need to deal with tricky state changes. But that is not the case here.

I´m not sure how far morphdom really goes. For simple state changes without changing the number or order of objects I cannot see the clue. And for more complex changes, where part´s of the DOM are exchanged, does it really work? How does it know that an object was at a different place in the DOM before?

Here is the DML version:

    sdiv("","width: 300px; display: flex; align-items: center; flex-flow: column; color: white; border: 1px solid white; ")
    let circle = div("","width: 100px; height: 100px; background-color: red; border-radius: 50%; margin: 20px;")
    function mySlider(s, iv=128){
      sdiv("","display: flex; ")
      span(s)
      let sl = slider({ max:255,  min: 0, value: iv} )
      sl.oninput = () => {
        sp.textContent = sl.value
        setColor()
      }
      let sp = span(sl.value,"width: 30px;")
      unselectBase()
      return sl
    }
    let R = mySlider("R",255)
    let G = mySlider("G")
    let B = mySlider("B")
    unselectBase()
    function setColor(){ circle.style.backgroundColor = `rgb(${R.value},${G.value},${B.value})`}; setColor()
Enter fullscreen mode Exit fullscreen mode

Live demo here

Collapse
 
artydev profile image
artydev • Edited

Hi Eckehard

Thank you for your comment :-).
Don't forget that MVU is essentially DML. I have only slim it and add Morphdom, HTML and SVG.

All you can do in DML you can accomplish it with MVU.

For this simple case, you are right Morphdom is not really needeed.
But I have created MVU for further purpose.
My goal is to stick with the SAM pattern.
Look at what I want to accomplish Meiosis

Here is a lighter version with MVU
slider

const { html, dom, udom, render, svg, m } = mvu.MVU;
const mcircle = () => m('div')('', `width:40px;height:40px;background:red;border-radius:50%`);
const slider = (min, max, value) => m('input')("", {type : "range", style:"display:block", max, min, value});
function setColor(elt, R, G, B){ elt.style.backgroundColor = `rgb(${R.value},${G.value},${B.value})`}; 
function App () {
  const app = dom ();
  const circle = mcircle ();
  const [R, G, B] = [slider(0, 255, 128), slider(0, 255, 23), slider(0, 255, 67)];
  udom();
  [R, G, B].forEach((s) => {s.oninput = () => setColor(circle, R, G, B)});
  setColor(circle, R, G, B);
  return app;
}
render(app, App());
Enter fullscreen mode Exit fullscreen mode
Collapse
 
efpage profile image
Eckehard

The core of DML is to enable a pure, object oriented design pattern for web applications. As we have seen, this works great using a functional appoach to create DOM elements, or using the HTML-syntax. Finally, this is only a question of personal taste and I would like to enable both flavours ion parallel.

But this is only the surface. The "big deal" is the tight coupeling of DOM elements to Javascript. This allows to use build "scoped" DOM elements, that are only visible in the local scope.

Usually, you do not need any kind of external "state management" in an OOP-application. I is more or less against the principles or OO to have some external logic that controls the state. States are always private, and each object needs to care for it´s own state. State management often is trivial on this level, so using some kind of "state management tool" on object level is useless in most cases.

There will be a need to deal with "global state changes". Assume, your app wants to close. It needs to ask all objects to do some preparations to close. So there is a need to have some communication between objects. But I assume, this is different from the use of a stat management tool.

By the way: Do you think it would be possible to implement a state manangement logic, that does not need to call "render"?

Thread Thread
 
artydev profile image
artydev

Hi Eckehard,

As you said Functional or OOP is just a matter of state.
Both, can be easily handled as you see.

If you have to make your components updated from a global state or (static in class), you will have to use a 'render' to update them....

Thread Thread
 
efpage profile image
Eckehard

Can you give an example? Why not update the component directly?

It seems, that in most cases state changes of dom elements are handled pertty well by the browser. This might be different if you need to exchange larger portions of a page. Usually i build those elements completely in memory before attaching them to the dom, so it is up to the browser to care for a smooth transition. Do you think, dom morphing does the job better?

The only advantage I can see is, that you have better control about the moment you call render(), but til now, event based state transtiton woked well enough for me.

Thread Thread
 
artydev profile image
artydev • Edited

Eckehard,

It seems we have a totally different background in the way we see web app development.

I am totally in 'functional way' and not in OOP, again, it is pure matter of philosophy

I suggest you to read the documentation MeiosisDoc.

There are some samples with Mithril, Preact...

Regards

Thread Thread
 
efpage profile image
Eckehard

Hy,

I do not think, OOP and FP live on different planets. The are even not that contradictionary as many people think. As we see, the DML core is useful in both concepts, but this is simple procedural code that is neither OOP not FP.

Inside, classes are very similar to old fashioned procedural programs, using (class-) global variables etc.. You can easily get the same spaghetti-code inside a class that we had in old fashioned C-programs. Why not apply the principles of FP to this code? Just, it needs to make sense.

I assume, FP might make code management easier in large projects, but referring to the DOM, FP is not that ideal. The DOM is stateful, so you always need some extra effort to bind functional code to the DOM, even with DOM-diffing. I was not amazed to find this site about morphDom. That was just what I expected.

Please check out my latest project to see, if this is "slow" by any means. This is just made with DML, page rendering takes about 2 - 4 ms for each page. If you have any questions about the project or the future of DML, please send me an email...

Thread Thread
 
artydev profile image
artydev • Edited

Hy Eckehard,

In fact, in my specific case, it's rather functional reactive programming (SAM Patern).
Morphdom does not loose focus on change look here Focus

I will send you a feedback for your project