on cd8ade6 help sign in
elk/libraries/Native/Signal/Keyboard.js
113 lines 3.0 kB history raw
2Elm.Native.Keyboard = function(elm) {
3 'use strict';
4 elm.Native = elm.Native || {};
5 if (elm.Native.Keyboard) return elm.Native.Keyboard;
7 // Duplicated from Native.Signal
8 function send(node, timestep, changed) {
9 var kids = node.kids;
10 for (var i = kids.length; i--; ) {
11 kids[i].recv(timestep, changed, node.id);
12 }
13 }
15 var Signal = Elm.Signal(elm);
16 var NList = Elm.Native.List(elm);
17 var Utils = Elm.Native.Utils(elm);
19 var downEvents = Signal.constant(0);
20 var upEvents = Signal.constant(0);
21 var blurEvents = Signal.constant(0);
23 elm.addListener([downEvents.id], document, 'keydown', function down(e) {
24 elm.notify(downEvents.id, e.keyCode);
25 });
27 elm.addListener([upEvents.id], document, 'keyup', function up(e) {
28 elm.notify(upEvents.id, e.keyCode);
29 });
31 elm.addListener([blurEvents.id], document, 'blur', function blur(e) {
32 elm.notify(blurEvents.id, NList.Nil);
33 });
35 function KeyMerge(down, up, blur) {
36 var args = [down,up,blur];
37 this.id = Utils.guid();
38 // Ignore starting values here
39 this.value = NList.Nil
40 this.kids = [];
42 var n = args.length;
43 var count = 0;
44 var isChanged = false;
46 this.recv = function(timestep, changed, parentID) {
47 ++count;
48 if (changed) {
49 // We know this a change must only be one of the following cases
50 if (parentID === down.id && !(NList.member(down.value)(this.value))) {
51 isChanged = true;
52 this.value = NList.Cons(down.value, this.value);
53 }
54 if (parentID === up.id) {
55 isChanged = true;
56 var notEq = function(kc) { return kc !== up.value };
57 this.value = NList.filter(notEq)(this.value);
58 }
59 if (parentID === blur.id) {
60 isChanged = true;
61 this.value = NList.Nil;
62 }
63 }
64 if (count == n) {
65 send(this, timestep, isChanged);
66 isChanged = false;
67 count = 0;
68 }
69 };
71 for (var i = n; i--; ) { args[i].kids.push(this); }
73 }
75 var keysDown = Signal.dropRepeats(new KeyMerge(downEvents,upEvents,blurEvents));
77 function keySignal(f) {
78 var signal = A2(Signal.lift, f, keysDown);
79 // what's the significance of these two following lines? -jpm
80 keysDown.defaultNumberOfKids += 1;
81 signal.defaultNumberOfKids = 0;
82 return signal;
83 }
85 function dir(up, down, left, right) {
86 function f(ks) {
87 var x = 0, y = 0;
88 while (ks.ctor === "::") {
89 switch (ks._0) {
90 case left : --x; break;
91 case right: ++x; break;
92 case up : ++y; break;
93 case down : --y; break;
94 }
95 ks = ks._1;
96 }
97 return { _:{}, x:x, y:y };
98 }
99 return keySignal(f);
100 }
102 function is(key) { return keySignal(NList.member(key)); }
104 var lastPressed = Signal.dropRepeats(downEvents);
106 return elm.Native.Keyboard = {
107 isDown:is,
108 directions:F4(dir),
109 keysDown:keysDown,
110 lastPressed:lastPressed
111 };
113};