@@ -0,0 +1,123 @@
1+
2+Elm.Keyboard = { Raw : function() {
3+ var keysDown = Elm.Signal.constant(["Nil"]);
4+ var charPressed = Elm.Signal.constant(["Nothing"]);
5+
6+ function remove(x,xs) {
7+ if (xs[0] === "Nil") return xs;
8+ if (xs[1] === x) return xs[2];
9+ return ["Cons", xs[1], remove(x,xs[2])];
10+ }
11+ function has(x,xs) {
12+ while (xs[0] !== "Nil") {
13+ if (xs[1] === x) return true;
14+ xs = xs[2];
15+ }
16+ return false;
17+ }
18+ Value.addListener(document, 'keydown', function(e) {
19+ if (has(e.keyCode, keysDown.value)) return;
20+ var hasListener = Dispatcher.notify(keysDown.id, ["Cons", e.keyCode, keysDown.value]);
21+ if (!hasListener)
22+ this.removeEventListener('keydown',arguments.callee,false);
23+ });
24+ Value.addListener(document, 'keyup', function(e) {
25+ var codes = remove(e.keyCode, keysDown.value);
26+ var hasListener = Dispatcher.notify(keysDown.id, codes);
27+ if (!hasListener)
28+ this.removeEventListener('keyup',arguments.callee,false);
29+ });
30+ Value.addListener(window, 'blur', function(e) {
31+ var hasListener = Dispatcher.notify(keysDown.id, ["Nil"]);
32+ if (!hasListener)
33+ this.removeEventListener('blur',arguments.callee,false);
34+ });
35+ Value.addListener(document, 'keypress', function(e) {
36+ var hasListener = Dispatcher.notify(charPressed.id, ["Just",e.charCode || e.keyCode]);
37+ Dispatcher.notify(charPressed.id, ["Nothing"]);
38+ if (!hasListener)
39+ this.removeEventListener('keypress',arguments.callee,false);
40+ });
41+ return {keysDown:keysDown,
42+ charPressed:charPressed};
43+ }()
44+};
45+
46+/*! Keyboard
47+These are nicely curated inputs from the keyboard. See the
48+[Keyboard.Raw library](/docs/Signal/KeyboardRaw.elm) for a
49+lower-level interface that will let you define more complicated behavior.
50+!*/
51+
52+(function() {
53+ function keySignal(f) {
54+ var signal = Elm.Signal.lift(f)(Elm.Keyboard.Raw.keysDown);
55+ Elm.Keyboard.Raw.keysDown.defaultNumberOfKids += 1;
56+ signal.defaultNumberOfKids = 0;
57+ return signal;
58+ }
59+
60+ function dir(left,right,up,down) {
61+ function f(ks) {
62+ var x = 0, y = 0;
63+ while (ks[0] == "Cons") {
64+ switch (ks[1]) {
65+ case left : --x; break;
66+ case right: ++x; break;
67+ case up : ++y; break;
68+ case down : --y; break;
69+ }
70+ ks = ks[2];
71+ }
72+ return { _:[true], x:[x], y:[y] };
73+ }
74+ return keySignal(f);
75+ }
76+
77+ function is(key) {
78+ function f(ks) {
79+ while (ks[0] == "Cons") {
80+ if (key == ks[1]) return true;
81+ ks = ks[2];
82+ }
83+ return false;
84+ }
85+ return keySignal(f);
86+ }
87+
88+ /*[Directions]*/
89+
90+ /** arrows : Signal { x:Int, y:Int }
91+ A signal of records indicating which arrow keys are pressed.
92+
93+ `{ x = 0, y = 0 }` when pressing no arrows.
94+ `{ x =-1, y = 0 }` when pressing the left arrow.
95+ `{ x = 1, y = 1 }` when pressing the up and right arrows.
96+ `{ x = 0, y =-1 }` when pressing the down, left, and right arrows.
97+ **/
98+ Elm.Keyboard.arrows = dir(37,39,38,40);
99+
100+ /** wasd : Signal { x:Int, y:Int }
101+ Just like the arrows signal, but this uses keys w, a, s, and d,
102+ which are common controls for many computer games.
103+ **/
104+ Elm.Keyboard.wasd = dir(65,68,87,83);
105+
106+ /*[Modifiers]*/
107+
108+ /** shift : Signal Bool
109+ Whether the shift key is pressed.
110+ **/
111+ Elm.Keyboard.shift = is(16);
112+
113+ /** ctrl : Signal Bool
114+ Whether the control key is pressed.
115+ **/
116+ Elm.Keyboard.ctrl = is(17);
117+
118+ /** space : Signal Bool
119+ Whether the space key is pressed.
120+ **/
121+ Elm.Keyboard.space = is(32);
122+
123+}());