1
1
# ` Elm ` (_ ish_ )
2
2
3
- ## (How to Build a Front-end Micro-Framework _ From Scratch_ )
4
-
5
3
![ elmlogo-ish] ( https://user-images.githubusercontent.com/194400/43213139-b70a4c68-902d-11e8-8162-3c7cb56b6360.png )
6
4
<!-- the colors are deliberately "a bit off" to emphasize that
7
5
this is a "inspired by" but really a "poor immitation" of Elm! -->
8
6
9
7
` Elm ` (_ ish_ ) is an ** ` Elm ` ** -_ inspired_ ` JavaScript ` (** ES5** )
10
- fully functional front-end _ micro_ -framework.[ <sup >1</sup >] ( #notes )
8
+ fully functional front-end _ micro_ -framework from _ scratch _ .[ <sup >1</sup >] ( #notes )
11
9
12
- <br />< br />
10
+ <br />
13
11
14
12
## _ Why?_
15
13
@@ -22,19 +20,19 @@ into a "micro framework" is to: <br />
22
20
*** simplify*** the Todo List application code
23
21
to _ just_
24
22
[ "** application logic** "] ( https://en.wikipedia.org/wiki/Business_logic ) . <br />
25
- ** b)** _ demonstrate _ a *** re-useable*** (_ fully-tested_ )
23
+ ** b)** _ demo _ a *** re-useable*** (_ fully-tested_ )
26
24
"** micro-framework** " that allows us
27
25
to _ practice_ using The Elm Architecture ("TEA").<br />
28
26
** c)** promote the ** mindset** of writing ** tests _ first_ **
29
27
and ** ` then ` ** the _ least_ amount of code necessary to pass the test
30
28
(_ while meeting the acceptance criteria_ ).
31
29
32
30
> _ ** Test** & ** Document-Driven Development** is ** easy** and it's ** easily**
33
- one of the ** best habits** to form in your software development career.
31
+ one of the ** best habits** to form in your software development " career" .
34
32
This walkthrough shows ** how** you can do it ** the right way**
35
33
from the ** start** of a project._
36
34
37
- <br />< br />
35
+ <br />
38
36
39
37
## _ What?_
40
38
@@ -64,7 +62,7 @@ https://github.com/dwyl/learn-elm-architecture-in-javascript/issues <br />
64
62
@dwyl is a "safe space" and we are all here to help don't be shy/afraid; <br />
65
63
the _ more_ questions you ask, the more you are helping yourself and _ others_ !
66
64
67
- <br />< br />
65
+ <br />
68
66
69
67
## _ How_ ?
70
68
@@ -131,10 +129,8 @@ The `view` function _invokes_ several "helper" functions
131
129
which create HTML ("DOM") elements e.g: ` <section> ` , ` <div> ` & ` <button> ` ;
132
130
these _ can_ (_ will_ ) be generalised (_ below_ ).
133
131
134
-
135
132
Let's start with a couple of "_ familiar_ " _ generic_ functions
136
- (_ which we used in the "counter-reset" example_ ):
137
- ` init ` , ` empty ` and ` mount ` . <br />
133
+ (_ which we used in the "counter-reset" example_ ): ` empty ` and ` mount ` . <br />
138
134
139
135
<br />
140
136
@@ -283,8 +279,6 @@ function empty(node) {
283
279
284
280
#### Add ` module.exports ` statement to "export" the ` empty ` function
285
281
286
- Remember to add a line in the ` module.exports ` Object at the end of the file:
287
-
288
282
Adding the function to the ` elmish.js ` file is a good _ start_ ,
289
283
but we need to *** ` export ` *** it to be able to _ invoke_ it in our test. <br />
290
284
Add the following code at the end of ` examples/todo-list/elmish.js ` :
@@ -310,7 +304,6 @@ Boom! our first test is passing!
310
304
(_ the test has ** 3 assertions** , that's why Tape says "tests 3. pass 3"_ ).
311
305
312
306
313
-
314
307
### ` mount ` the App
315
308
316
309
The ` mount ` function is the "glue" or "wiring" function that
@@ -590,7 +583,8 @@ The `JSDOC` comment for our `add_attributes` function is:
590
583
/**
591
584
* add_attributes applies the desired attributes to the desired node.
592
585
* Note: this function is "impure" because it "mutates" the node.
593
- * however it is idempotent; the "side effect" is only applied once.
586
+ * however it is idempotent; the "side effect" is only applied once
587
+ * and no other nodes in the DOM are "affected" (undesirably).
594
588
* @param {Array.<String>} attrlist list of attributes to be applied to the node
595
589
* @param {Object} node DOM node upon which attribute(s) should be applied
596
590
* @example
@@ -617,37 +611,98 @@ test('elmish.add_attributes applies class HTML attribute to a node', function (t
617
611
});
618
612
```
619
613
620
- Given the code in the test above,
621
- take a moment to think of how _ you_ would write,
614
+ If you (_ attempt to_ ) run this test (_ and you ** should** _ ),
615
+ you will see something like this:
616
+
617
+ ![ image] ( https://user-images.githubusercontent.com/194400/43414770-af5ee0e4-942b-11e8-9d1c-1cbab3adc136.png )
618
+
619
+ Test is failing because the ` elmish.add_attributes ` function does not _ exist_ .
620
+
621
+ Go ahead and _ create_ the ` elmish.add_attributes ` function
622
+ (_ just the function without passing the test_ ) and _ export_ it in ` elmish.js ` :
623
+ ``` js
624
+ /**
625
+ * add_attributes applies the desired attributes to the desired node.
626
+ * Note: this function is "impure" because it "mutates" the node.
627
+ * however it is idempotent; the "side effect" is only applied once
628
+ * and no other nodes in the DOM are "affected" (undesirably).
629
+ * @param {Array.<String>} attrlist list of attributes to be applied to the node
630
+ * @param {Object} node DOM node upon which attribute(s) should be applied
631
+ * @example
632
+ * // returns node with attributes applied
633
+ * div = add_attributes ([" class=item" , " id=mydiv" , " active=true" ], div);
634
+ */
635
+ function add_attributes (attrlist , node ) {
636
+ if (attrlist && attrlist .length ) {
637
+ attrlist .forEach (function (attr ) { // apply each prop in array
638
+ var a = attr .split (' =' );
639
+ switch (a[0 ]) {
640
+ // code to make test pass goes here ...
641
+ default :
642
+ break ;
643
+ }
644
+ });
645
+ }
646
+ return node;
647
+ }
648
+ // ... at the end of the file, "export" the add_attributes funciton:
649
+ if (typeof module !== ' undefined' && module .exports ) {
650
+ module .exports = {
651
+ add_attributes: add_attributes, // export the function so we can test it!
652
+ empty: empty,
653
+ mount: mount
654
+ }
655
+ }
656
+ ```
657
+
658
+ When you re-run the test you will see something like this:
659
+ ![ image] ( https://user-images.githubusercontent.com/194400/43416008-ff63d70e-942e-11e8-97ee-6544efb7d43a.png )
660
+ The function _ exists_ but it does not make the tests pass.
661
+ Your _ quest_ is to turn this ** ` 0 ` ** into a ** ` 1 ` ** .
662
+
663
+ Given the ** ` JSDOC ` ** comment and _ test_ above,
664
+ take a moment to think of how _ you_ would write
622
665
the ` add_attributes ` function to apply a CSS ` class ` to an element. <br />
623
666
Note: we have _ seen_ the code _ before_ in the ` counter ` example.
624
667
The difference is this time we want it to be "generic";
625
668
we want to apply a CSS ` class ` to _ any_ DOM node.
626
669
627
670
If you can, make the test _ pass_
628
671
by writing the ` add_attributes ` function.
629
- (_ don't forget to_ ` export ` _ the function at the end of the file_ ).
672
+ (_ don't forget to_ ` export ` _ the function at the bottom of the file_ ).
630
673
631
- If you get "stuck", checkout:
632
- https://github.com/dwyl/learn-elm-architecture-in-javascript/tree/master/examples/todo-list/elmish.js < br />
674
+ If you get "stuck", checkout the _ complete _ example :
675
+ [ /examples/todo-list/elmish.js ] ( https://github.com/dwyl/learn-elm-architecture-in-javascript/tree/master/examples/todo-list/elmish.js )
633
676
677
+ > ** Note 1** : it's not "cheating" to look at "the solution",
678
+ the whole point of having a step-by-step tutorial
679
+ is that you can fill-in any "gaps" if you get "stuck",
680
+ but you should only check _ after_ making
681
+ a good attempt to write the code _ yourself_ .
682
+ <br />
634
683
635
- > ** Note** : The ` add_attributes ` function is "impure" as it "mutates"
684
+ > ** Note 2 ** : The ` add_attributes ` function is "impure" as it "mutates"
636
685
the target DOM ` node ` , this is more of a "fact of life" in JavaScript,
637
686
and given that the application of attributes
638
687
to DOM node(s) is idempotent we aren't "concerned" with "side effects";
639
688
the attribute will only be applied _ once_ to the node
640
689
regardless of how many times the ` add_attributes ` function is called.
641
690
see: https://en.wikipedia.org/wiki/Idempotence
642
691
643
-
644
692
For reference, the Elm HTML Attributes function on Elm package is:
645
693
http://package.elm-lang.org/packages/elm-lang/html/2.0.0/Html-Attributes
646
694
695
+ Once you make the test _ pass_ you _ should_ see the following in your Terminal:
696
+ ![ image] ( https://user-images.githubusercontent.com/194400/43416304-d06339da-942f-11e8-9546-06af9c494a45.png )
697
+
698
+ <!-- Onto the next one! https://vimeo.com/8503138 -->
699
+
700
+ <br />
701
+
647
702
#### Input ` placeholder ` Attribute
648
703
649
704
The ` <input> ` form element (_ where we create new Todo List items_ )
650
- has a helpful ` placeholder ` _ prompting_ us with a question:
705
+ has a helpful ` placeholder ` attribute _ prompting_ us with a question:
651
706
"_ What needs to be done?_ "
652
707
653
708
Add the following test to the ` test/elmish.test.js ` file: <br />
@@ -666,7 +721,14 @@ test('elmish.add_attributes set placeholder on <input> element', function (t) {
666
721
});
667
722
```
668
723
669
- Write the necessary code to make this test _ pass_ in ` elmish.js ` .
724
+
725
+
726
+
727
+ Write the necessary code in the ` add_attributes ` function of ` elmish.js `
728
+ to make this test _ pass_ .
729
+
730
+ If you get "stuck", checkout the _ complete_ example:
731
+ [ /examples/todo-list/elmish.js] ( https://github.com/dwyl/learn-elm-architecture-in-javascript/tree/master/examples/todo-list/elmish.js )
670
732
671
733
672
734
#### Input ` autofocus `
@@ -771,7 +833,8 @@ test.only('elmish.add_attributes set "for" attribute <label> element', function
771
833
});
772
834
```
773
835
774
- Write the "case" in to make this test _ pass_ in ` elmish.js ` .
836
+ Add the "` case ` " in the ` add_attributes ` function's ` switch ` statement
837
+ to make this test _ pass_ in ` elmish.js ` .
775
838
776
839
777
840
#### ` <input> ` attribute ` type `
@@ -1503,7 +1566,7 @@ We are going to make **3 adjustments** to this code
1503
1566
to use ` setItem ` and ` getItem ` ,
1504
1567
but _ first_ let's write a *** test*** for the desired outcome!
1505
1568
1506
- Add the following _ test code_ to your ` test/elmish.test.js ` file: <br />:
1569
+ Add the following _ test code_ to your ` test/elmish.test.js ` file: <br />
1507
1570
1508
1571
``` js
1509
1572
// Testing localStorage requires a "polyfil" because it's unavailable in JSDOM:
0 commit comments