-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
borrow code from example/counter-reset for Multiple Counters example #40
- Loading branch information
Showing
5 changed files
with
197 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// 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(model, action) { // 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(signal, model, root) { | ||
empty(root); // clear root element before | ||
[ // 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(function(el){ root.appendChild(el) }); // 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(model, action); // update model according to action | ||
view(signal, model, root); // subsequent re-rendering | ||
}; | ||
}; | ||
view(signal, model, root); // 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; | ||
} | ||
|
||
function init(doc){ | ||
document = doc; // this is used for instantiating JSDOM. ignore! | ||
} | ||
|
||
/* The code block below ONLY Applies to tests run using Node.js */ | ||
/* istanbul ignore next */ | ||
if (typeof module !== 'undefined' && module.exports) { | ||
module.exports = { | ||
view: view, | ||
mount: mount, | ||
update: update, | ||
div: div, | ||
button: button, | ||
empty: empty, | ||
init: init | ||
} | ||
} else { init(document); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!DOCTYPE html> | ||
<html lang=”en-GB”> | ||
<head> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | ||
<meta name="viewport" | ||
content="width=device-width, initial-scale=1.0, user-scalable=yes"> | ||
<title>Elm Architecture in JS - Counter Reset</title> | ||
<link rel="shortcut icon" | ||
href="http://www.dwyl.io/images/favicon.ico" type="image/x-icon"> | ||
<!-- CSS Styles are 100% optional. but they make it look *much* nicer --> | ||
<link rel="stylesheet" href="../style.css"> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
<script src="counter.js" data-cover></script> <!-- load counter --> | ||
<script> | ||
// Initialise the app by "mounting" it passing in MUV Object & "root" DOM node | ||
mount(0, update, view, 'app'); | ||
</script> | ||
|
||
<!-- Below this point is all related to the Tests for the App --> | ||
<div id="test-app"></div> <!-- Create a test-app div to mount the app --> | ||
<div id="qunit"></div> <!-- test results are displayed here --> | ||
<!-- Load the QUnit CSS file from CDN - require to display our tests --> | ||
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-1.18.0.css"> | ||
<!-- Load the QUnit Testing Framework from CDN - to run the tests --> | ||
<script src="https://code.jquery.com/qunit/qunit-1.18.0.js"></script> | ||
<!-- Load Blanket.js from CDN - for test coverage stats --> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/blanket.js/1.1.4/blanket.js"> | ||
</script> | ||
<script src="test.js"></script> <!-- always load test.js last --> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
var id = 'test-app'; | ||
|
||
test('Test Update update(0) returns 0 (current state)', function(assert) { | ||
var result = update(0); | ||
assert.equal(result, 0); | ||
}); | ||
|
||
test('Test Update increment: update(1, "inc") returns 2', function(assert) { | ||
var result = update(1, "inc"); | ||
assert.equal(result, 2); | ||
}); | ||
|
||
test('Test Update decrement: update(3, "dec") returns 2', function(assert) { | ||
var result = update(1, "dec"); | ||
assert.equal(result, 0); | ||
}); | ||
|
||
test('Test negative state: update(-9, "inc") returns -8', function(assert) { | ||
var result = update(-9, "inc"); | ||
assert.equal(result, -8); | ||
}); | ||
|
||
test('mount({model: 7, update: update, view: view}, "' | ||
+ id +'") sets initial state to 7', function(assert) { | ||
mount(7, update, view, id); | ||
var state = |