@@ -4,29 +4,79 @@ Elm.Native.Keyboard = function(elm) {
4 elm.Native = elm.Native || {};
4 elm.Native = elm.Native || {};
5 if (elm.Native.Keyboard) return elm.Native.Keyboard;
5 if (elm.Native.Keyboard) return elm.Native.Keyboard;
7+ // Duplicated from Native.Signal
8+ function send(node, timestep, changed) {
10+ for (var i = kids.length; i--; ) {
11+ kids[i].recv(timestep, changed, node.id);
7 var Signal = Elm.Signal(elm);
15 var Signal = Elm.Signal(elm);
8 var NList = Elm.Native.List(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);
27+ elm.addListener([upEvents.id], document, 'keyup', function up(e) {
28+ elm.notify(upEvents.id, e.keyCode);
31+ elm.addListener([blurEvents.id], document, 'blur', function blur(e) {
32+ elm.notify(blurEvents.id, NList.Nil);
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
44+ var isChanged = false;
10− var keysDown = Signal.constant(NList.Nil);
46+ this.recv = function(timestep, changed, parentID) {
11− var lastKey = Signal.constant('\0');
47+ ++count;
13− elm.addListener([keysDown.id], document, 'keydown', function down(e) {
49+ // We know this a change must only be one of the following cases
14− if (NList.member(e.keyCode)(keysDown.value)) return;
50+ if (parentID === down.id && !(NList.member(down.value)(this.value))) {
15− elm.notify(keysDown.id, NList.Cons(e.keyCode, keysDown.value));
51+ isChanged = true;
52+ this.value = NList.Cons(down.value, this.value);
17− elm.addListener([keysDown.id], document, 'keyup', function up(e) {
54+ if (parentID === up.id) {
18− function notEq(kc) { return kc !== e.keyCode; }
56+ var notEq = function(kc) { return kc !== up.value };
19− elm.notify(keysDown.id, NList.filter(notEq)(keysDown.value));
57+ this.value = NList.filter(notEq)(this.value);
21− elm.addListener([keysDown.id], document, 'blur', function blur(e) {
59+ if (parentID === blur.id) {
22− elm.notify(keysDown.id, NList.Nil);
60+ isChanged = true;
61+ this.value = NList.Nil;
24− elm.addListener([lastKey.id], document, 'keypress', function press(e) {
64+ if (count == n) {
25− elm.notify(lastKey.id, e.charCode || e.keyCode);
65+ send(this, timestep, isChanged);
26− });
66+ isChanged = false;
71+ for (var i = n; i--; ) { args[i].kids.push(this); }
75+ var keysDown = Signal.dropRepeats(new KeyMerge(downEvents,upEvents,blurEvents));
28 function keySignal(f) {
77 function keySignal(f) {
29− var signal = Signal.dropRepeats(A2(Signal.lift, f, keysDown));
78+ var signal = A2(Signal.lift, f, keysDown);
79+ // what's the significance of these two following lines? -jpm
30 keysDown.defaultNumberOfKids += 1;
80 keysDown.defaultNumberOfKids += 1;
31 signal.defaultNumberOfKids = 0;
81 signal.defaultNumberOfKids = 0;
32 return signal;
82 return signal;
@@ -51,11 +101,13 @@ Elm.Native.Keyboard = function(elm) {
52 function is(key) { return keySignal(NList.member(key)); }
102 function is(key) { return keySignal(NList.member(key)); }
104+ var lastPressed = Signal.dropRepeats(downEvents);
54 return elm.Native.Keyboard = {
106 return elm.Native.Keyboard = {
55− isDown:is,
107+ isDown:is,
56− directions:F4(dir),
108+ directions:F4(dir),
57− keysDown:keysDown,
109+ keysDown:keysDown,
58− lastPressed:lastKey
110+ lastPressed:lastPressed