on efdb99f help sign in
elk/libraries/Native/Signal/Keyboard.js
120 lines 3.3 kB history raw
1Elm.Native.Keyboard = {};
2Elm.Native.Keyboard.make = function(elm) {
4 elm.Native = elm.Native || {};
5 elm.Native.Keyboard = elm.Native.Keyboard || {};
6 if (elm.Native.Keyboard.values) return elm.Native.Keyboard.values;
8 // Duplicated from Native.Signal
9 function send(node, timestep, changed) {
10 var kids = node.kids;
11 for (var i = kids.length; i--; ) {
12 kids[i].recv(timestep, changed, node.id);
13 }
14 }
16 var Signal = Elm.Signal.make(elm);
17 var NList = Elm.Native.List.make(elm);
18 var Utils = Elm.Native.Utils.make(elm);
20 var NS = Elm.Native.Signal.make(elm);
21 var downEvents = NS.input(0);
22 var upEvents = NS.input(0);
23 var blurEvents = NS.input(0);
25 elm.addListener([downEvents.id], document, 'keydown', function down(e) {
26 elm.notify(downEvents.id, e.keyCode);
27 });
29 elm.addListener([upEvents.id], document, 'keyup', function up(e) {
30 elm.notify(upEvents.id, e.keyCode);
31 });
33 elm.addListener([blurEvents.id], document, 'blur', function blur(e) {
34 elm.notify(blurEvents.id, NList.Nil);
35 });
37 function KeyMerge(down, up, blur) {
38 this.nodeType = "merge";
40 var args = [down,up,blur];
41 this.id = Utils.guid();
42 // Ignore starting values here
43 this.value = NList.Nil
44 this.kids = [];
46 var n = args.length;
47 var count = 0;
48 var isChanged = false;
50 this.recv = function(timestep, changed, parentID) {
51 ++count;
52 if (changed) {
53 // We know this a change must only be one of the following cases
54 if (parentID === down.id && !(NList.member(down.value)(this.value))) {
55 isChanged = true;
56 this.value = NList.Cons(down.value, this.value);
57 }
58 if (parentID === up.id) {
59 isChanged = true;
60 var notEq = function(kc) { return kc !== up.value };
61 this.value = NList.filter(notEq)(this.value);
62 }
63 if (parentID === blur.id) {
64 isChanged = true;
65 this.value = NList.Nil;
66 }
67 }
68 if (count == n) {
69 send(this, timestep, isChanged);
70 isChanged = false;
71 count = 0;
72 }
73 };
75 for (var i = n; i--; ) { args[i].kids.push(this); }
77 }
79 var keysDown = Signal.dropRepeats(new KeyMerge(downEvents,upEvents,blurEvents));
81 function keySignal(f) {
82 var signal = A2(Signal.lift, f, keysDown);
83 // must set the default number of kids to make it possible to filter
84 // these signals if they are not actually used.
85 keysDown.defaultNumberOfKids += 1;
86 signal.defaultNumberOfKids = 1;
87 var filtered = Signal.dropRepeats(signal)
88 filtered.defaultNumberOfKids = 0;
89 return filtered;
90 }
92 function dir(up, down, left, right) {
93 function f(ks) {
94 var x = 0, y = 0;
95 while (ks.ctor === "::") {
96 switch (ks._0) {
97 case left : --x; break;
98 case right: ++x; break;
99 case up : ++y; break;
100 case down : --y; break;
101 }
102 ks = ks._1;
103 }
104 return { _:{}, x:x, y:y };
105 }
106 return keySignal(f);
107 }
109 function is(key) { return keySignal(NList.member(key)); }
111 var lastPressed = downEvents;
113 return elm.Native.Keyboard.values = {
114 isDown:is,
115 directions:F4(dir),
116 keysDown:keysDown,
117 lastPressed:lastPressed
118 };
120};