UNPKG

todomvc-example-in-vanilla-javascript-using-elm-architecture-

Version:

Learn how to use The Elm Architecture in JavaScript to create functional and fast UI!

93 lines (82 loc) 3.87 kB
// this file is borrowed from: // https://github.com/dwyl/learn-elm-architecture-in-javascript/blob/master/examples/counter-reset/counter.js // it is included here purely for testing the "elmish" functions. // Define the Component's Actions: var Inc = 'inc'; // increment the counter var Dec = 'dec'; // decrement the counter var Res = 'reset'; // reset counter: git.io/v9KJk function update (action, model) { // Update function takes the current state switch(action) { // and an action (String) runs a switch case Inc: return model + 1; // add 1 to the model case Dec: return model - 1; // subtract 1 from model case Res: return 0; // reset state to 0 (Zero) git.io/v9KJk default: return model; // if no action, return curent state. } // (default action always returns current) } function view(model, signal) { return container([ // Store DOM nodes in an array button('+', signal, Inc), // then iterate to append them div('count', model), // create div with stat as text button('-', signal, Dec), // decrement counter button('Reset', signal, Res) // reset counter ]); // forEach is ES5 so IE9+ } // yes, for loop is "faster" than forEach, but readability trumps "perf" here! // Mount Function receives all MUV and mounts the app in the "root" DOM Element function mount(model, update, view, root_element_id) { var root = document.getElementById(root_element_id); // root DOM element function signal(action) { // signal function takes action return function callback() { // and returns callback model = update(action, model); // update model according to action empty(root); root.appendChild(view(model, signal)); // subsequent re-rendering }; }; root.appendChild(view(model, signal)); // render initial model (once) } // The following are "Helper" Functions which each "Do ONLY One Thing" and are // used in the "View" function to render the Model (State) to the Browser DOM: // empty the contents of a given DOM element "node" (before re-rendering) function empty(node) { while (node.firstChild) { node.removeChild(node.firstChild); } } // Inspired by: stackoverflow.com/a/3955238/1148249 function button(text, signal, action) { var button = document.createElement('button'); var text = document.createTextNode(text); // human-readable button text button.appendChild(text); // text goes *inside* not attrib button.className = action; // use action as CSS class button.id = action; // console.log(signal, ' action:', action) button.onclick = signal(action); // onclick tells how to process return button; // return the DOM node(s) } // how to create a button in JavaScript: stackoverflow.com/a/8650996/1148249 function div(divid, text) { var div = document.createElement('div'); div.id = divid; div.className = divid; if(text !== undefined) { // if text is passed in render it in a "Text Node" var txt = document.createTextNode(text); div.appendChild(txt); } return div; } // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section function container(elements) { var con = document.createElement('section'); con.className = 'counter'; elements.forEach(function(el) { con.appendChild(el) }); return con; } /* The code block below ONLY Applies to tests run using Node.js */ /* istanbul ignore else */ if (typeof module !== 'undefined' && module.exports) { module.exports = { view: view, mount: mount, update: update, div: div, button: button, empty: empty, } }