123 lines
3.3 KiB
JavaScript
123 lines
3.3 KiB
JavaScript
|
|
Elm.Keyboard = { Raw : function() {
|
|
var keysDown = Elm.Signal.constant(["Nil"]);
|
|
var charPressed = Elm.Signal.constant(["Nothing"]);
|
|
|
|
function remove(x,xs) {
|
|
if (xs[0] === "Nil") return xs;
|
|
if (xs[1] === x) return xs[2];
|
|
return ["Cons", xs[1], remove(x,xs[2])];
|
|
}
|
|
function has(x,xs) {
|
|
while (xs[0] !== "Nil") {
|
|
if (xs[1] === x) return true;
|
|
xs = xs[2];
|
|
}
|
|
return false;
|
|
}
|
|
Value.addListener(document, 'keydown', function(e) {
|
|
if (has(e.keyCode, keysDown.value)) return;
|
|
var hasListener = Dispatcher.notify(keysDown.id, ["Cons", e.keyCode, keysDown.value]);
|
|
if (!hasListener)
|
|
this.removeEventListener('keydown',arguments.callee,false);
|
|
});
|
|
Value.addListener(document, 'keyup', function(e) {
|
|
var codes = remove(e.keyCode, keysDown.value);
|
|
var hasListener = Dispatcher.notify(keysDown.id, codes);
|
|
if (!hasListener)
|
|
this.removeEventListener('keyup',arguments.callee,false);
|
|
});
|
|
Value.addListener(window, 'blur', function(e) {
|
|
var hasListener = Dispatcher.notify(keysDown.id, ["Nil"]);
|
|
if (!hasListener)
|
|
this.removeEventListener('blur',arguments.callee,false);
|
|
});
|
|
Value.addListener(document, 'keypress', function(e) {
|
|
var hasListener = Dispatcher.notify(charPressed.id, ["Just",e.charCode || e.keyCode]);
|
|
Dispatcher.notify(charPressed.id, ["Nothing"]);
|
|
if (!hasListener)
|
|
this.removeEventListener('keypress',arguments.callee,false);
|
|
});
|
|
return {keysDown:keysDown,
|
|
charPressed:charPressed};
|
|
}()
|
|
};
|
|
|
|
/*! Keyboard
|
|
These are nicely curated inputs from the keyboard. See the
|
|
[Keyboard.Raw library](/docs/Signal/KeyboardRaw.elm) for a
|
|
lower-level interface that will let you define more complicated behavior.
|
|
!*/
|
|
|
|
(function() {
|
|
function keySignal(f) {
|
|
var signal = Elm.Signal.lift(f)(Elm.Keyboard.Raw.keysDown);
|
|
Elm.Keyboard.Raw.keysDown.defaultNumberOfKids += 1;
|
|
signal.defaultNumberOfKids = 0;
|
|
return signal;
|
|
}
|
|
|
|
function dir(left,right,up,down) {
|
|
function f(ks) {
|
|
var x = 0, y = 0;
|
|
while (ks[0] == "Cons") {
|
|
switch (ks[1]) {
|
|
case left : --x; break;
|
|
case right: ++x; break;
|
|
case up : ++y; break;
|
|
case down : --y; break;
|
|
}
|
|
ks = ks[2];
|
|
}
|
|
return { _:[true], x:[x], y:[y] };
|
|
}
|
|
return keySignal(f);
|
|
}
|
|
|
|
function is(key) {
|
|
function f(ks) {
|
|
while (ks[0] == "Cons") {
|
|
if (key == ks[1]) return true;
|
|
ks = ks[2];
|
|
}
|
|
return false;
|
|
}
|
|
return keySignal(f);
|
|
}
|
|
|
|
/*[Directions]*/
|
|
|
|
/** arrows : Signal { x:Int, y:Int }
|
|
A signal of records indicating which arrow keys are pressed.
|
|
|
|
`{ x = 0, y = 0 }` when pressing no arrows.
|
|
`{ x =-1, y = 0 }` when pressing the left arrow.
|
|
`{ x = 1, y = 1 }` when pressing the up and right arrows.
|
|
`{ x = 0, y =-1 }` when pressing the down, left, and right arrows.
|
|
**/
|
|
Elm.Keyboard.arrows = dir(37,39,38,40);
|
|
|
|
/** wasd : Signal { x:Int, y:Int }
|
|
Just like the arrows signal, but this uses keys w, a, s, and d,
|
|
which are common controls for many computer games.
|
|
**/
|
|
Elm.Keyboard.wasd = dir(65,68,87,83);
|
|
|
|
/*[Modifiers]*/
|
|
|
|
/** shift : Signal Bool
|
|
Whether the shift key is pressed.
|
|
**/
|
|
Elm.Keyboard.shift = is(16);
|
|
|
|
/** ctrl : Signal Bool
|
|
Whether the control key is pressed.
|
|
**/
|
|
Elm.Keyboard.ctrl = is(17);
|
|
|
|
/** space : Signal Bool
|
|
Whether the space key is pressed.
|
|
**/
|
|
Elm.Keyboard.space = is(32);
|
|
|
|
}());
|