Javascript keyboard event in an object - javascript

I got my keyboard working in a simple way:
rightPressed = false;
onKeyDown = function(pressEvent) {
if (pressEvent.keyCode == 39) rightPressed = true;
}
onKeyUp = function(pressEvent) {
if (pressEvent.keyCode == 39) rightPressed = false;
}
$(document).keydown(onKeyDown);
$(document).keyup(onKeyUp);
And it worked. Then i tried to put it all in a class:
function Tkeyboard(){
this.rightPressed = false;
this.onKeyDown = function(pressEvent) {
if (pressEvent.keyCode == 39) { this.rightPressed = true; alert("boom!"); }
}
this.onKeyUp = function(pressEvent) {
if (pressEvent.keyCode == 39) { this.rightPressed = false; }
}
$(document).keydown(this.onKeyDown);
$(document).keyup(this.onKeyUp);
}
In initialization I created an object:
keys = new Tkeyboard;
In main loop i put action:
if ( keys.rightPressed ) { rx+=1;}
And now it fails. The interesting part of the problem is that alert("boom!") is called, so variable should get modified too...
I would be grateful for any ideas.

The keydown/up callback loses its original scope when the it is actually run. You'll need to bind the callback to this. In the Prototype Framework, you would do this:
function Tkeyboard() {
this.rightPressed = false;
$(document).keydown(this.onKeyDown.bind(this));
$(document).keyup(this.onKeyUp.bind(this));
}
Tkeyboard.prototype.onKeyDown = function(pressEvent) {
if (pressEvent.keyCode == 39) { this.rightPressed = true; alert("boom!"); }
};
Tkeyboard.prototype.onKeyUp = function(pressEvent) {
if (pressEvent.keyCode == 39) { this.rightPressed = false; }
};
It should be similar in jQuery.
If you need an idea of how to build a full fledged keyboard class, check out the one I wrote.

In an event handler in jQuery (and in DOM events), this refers to the element the event is subscribed on (document in the sample). Use a closure if you want to refer to the original object.
function Tkeyboard(){
var self = this;
this.rightPressed = false;
this.onKeyDown = function(pressEvent) {
if (pressEvent.keyCode == 39) { self.rightPressed = true; alert("boom!"); }
}
this.onKeyUp = function(pressEvent) {
if (pressEvent.keyCode == 39) { self.rightPressed = false; }
}
$(document).keydown(this.onKeyDown);
$(document).keyup(this.onKeyUp);
}

this is set to the DOM element (in this case document) from which the event handler is called. In general, this is not bound to the object in javascript:
var a = {
f: function () {}
};
var b = { f: a.f};
var f = a.f;
a.f(); // this === a
b.f(); // this === b
f(); // this === window
One commonly used workaround is to bind this to a wrapper function:
function bind(func, that) {
return function() {
func.apply(that, arguments);
}
}
//...
$(document).keydown(bind(this.onKeyDown, this));
Or you could use closures:
function Tkeyboard() {
var that = this;
// use 'that' from here on

you can initiate new function it will work
function Tkeyboard() {
this.rightPressed = false;
this.onKeyDown = function (pressEvent) {
if (pressEvent.keyCode == 39) {
this.rightPressed = true;
console.log(this.rightPressed )
alert('boom')
}
}
this.onKeyUp = function (pressEvent) {
if (pressEvent.keyCode == 39) {
this.rightPressed = false;
console.log(this.rightPressed )
}
}
this.events = function(){
document.addEventListener('keydown', this.onKeyDown);
document.addEventListener('keyup', this.onKeyUp);
}
}
const keys = new Tkeyboard;
keys.events();

Related

Event when space is pressing, only one time

I have some issues: I have this : (in a function..)
var space = 0;
setInterval(space, 20);
var keys = {}
$(document).keydown(function(e) {
keys[e.keyCode] = true;
});
$(document).keyup(function(e) {
delete keys[e.keyCode];
});
function space() {
for (var direction in keys) {
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 32) {
space++;
console.log(space);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
32 == Space key, but I saw in the console that space is pressed 3 times (space == 3), keyup keypress and keydown (I think), how can I have just "space = 1" when space is pressed ?
What seems to be happening is that since it's running every 20 ms, as you hold down the space bar the space function is continuously incrementing the count. I added a flag to prevent another execution until the key is released and it works fine. Really you should just use the keypress event and check there if the keyCode === 32 to track your count. Fewer events will be fired. If you want to see what was happening you can comment out the flag and check the console.
var spaceCount = 0;
var running = false;
var keys = {}
$(document).keydown(function(e) {
console.log("keycode", e.keyCode);
keys[e.keyCode] = true;
});
$(document).keyup(function(e) {
console.log("keyup")
delete keys[e.keyCode];
running = false;
});
function space() {
if(running) return;
for (var direction in keys) {
running = true;
console.log(direction);
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 32) {
spaceCount++;
console.log("count: " + spaceCount);
console.log(keys);
}
}
}
setInterval(space, 20);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I hope that will be helpful:
var space = 0;
var keys = {};
var keys2 = {};
$(document).keydown(function(e) {
keys[e.keyCode] = true;
});
$(document).keyup(function(e) {
keys[e.keyCode] = false;
});
setInterval(function(){spacing()}, 20);
function spacing() {
if (keys[32] && !keys2[32])
{
space++;
keys2[32] = true;
}
else if(!keys[32])
{
keys2[32] = false;
}
console.log(space);
}

Keyboard Inputs [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
I'm coding a project and I've got a problem when I try getting keyboard input in a dedicated class.
So this is my Controller class :
Controller = function() {
// Initialisation clavier
document.onkeydown = this.onKeyDown;
document.onkeyup = this.onKeyUp;
// Touches
this.left = false;
this.up = false;
this.down = false;
this.right = false;
}
// Touche appuyée
Controller.prototype.onKeyDown = function(event) {
if (event.keyCode == 37) {
this.left = true;
}
else if (event.keyCode == 38) {
this.up = true;
}
else if (event.keyCode == 39) {
this.down = true;
}
else if (event.keyCode == 40) {
this.right = true;
}
}
// Touche relâchée
Controller.prototype.onKeyUp = function(event) {
if (event.keyCode == 37) {
this.left = false;
}
else if (event.keyCode == 38) {
this.up = false;
}
else if (event.keyCode == 39) {
this.down = false;
}
else if (event.keyCode == 40) {
this.right = false;
}
}
... with which I create an occurence during initialization. But when I try to get boolean state in an other class :
// Déplacement
Player.prototype.move = function() {
if (controler.left) {
this.posHorizontal -= this.speed;
}
}
this isn't working ! When I display the state in the controller class it return 'true' but not in another classes. I'v got no error but only a 'false' displayed (i've tried with console.log but no way).
Thanks for help !
When the browser calls onKeyDown and onKeyUp methods, after the events happen, the this keyword inside the functions points to the document not to the Controller instance.
change the lines
document.onkeydown = this.onKeyDown;
document.onkeyup = this.onKeyUp;
to
document.onkeydown = this.onKeyDown.bind(this);
document.onkeyup = this.onKeyUp.bind(this);
and it should fix the issue.

get keycode with shiftkey

I want to get keyCode if they are pressed with shift Key,
for ex. I press a and then b. Then I want to store it in one array like this [shiftkey,65,66] please suggest me if this is possible or I am going wrong.
You can try this sanjay:
<input id="down" type="text"/>
var your_array = [];
document.onkeydown = function (e) {
var keyPress;
if (typeof event !== 'undefined') {
keyPress = this.value + String.fromCharCode(e.keyCode);
}
else if (e) {
keyPress = e.which;
}
if(keyPress == '16'){
keyPress = 'shift';
}
your_array.push(keyPress);
alert(your_array);
// returns [shift,65,66];
return false; // Prevents the default action
};
var a = [];
var wait = true;
window.onkeydown = function (e) {
if (wait) {
if (a[0] != e.keyCode) { a[0] = e.keyCode; }
}
wait = false;
window.addEventListener('keyup', key_up, false);
}
function key_up(e) {
a[1] = e.keyCode;
if (a[0] == a[1]) { a = []; }
wait = true;
window.removeEventListener('keyup', key_up, false);
console.log(a);
alert(a);
}
var pressedKeysSeries = [];
$(document).on('keyup', function (e) { pressedKeysSeries = []; });
$(document).on('keydown', function (e) {
if (e.shiftKey && pressedKeysSeries.indexOf(e.key) === -1) {
pressedKeysSeries.push(e.key);
}
console.log(pressedKeysSeries);
});

Javascript ActiveElement and Keydown Event Listener

I'm new to Javascript and I'm trying to make the following code scan to see if a textbox with an id="lessonNum" is active, if it is not i would like to send a .click to a submit button with an id="A" when I press 'a' on the keyboard. Right now when I select the textbox I get an alert, but when I don't have it selected it doesn't pick up my keydown. Please Help!
function GetActive () {
if (document.activeElement.id == 'lessonNum') {
alert('lessonNum is active');
var b1=new Boolean(1);
} else {
var b1=new Boolean(0);
}
}
document.addEventListener("keydown", keyDownTextField, false);
function keyDownTextField(e) {
var keyCode = e.keyCode;
if(keyCode==65) {
if(b1==0) {
alert('a has been pressed');
document.getElementById('A').click();
}
}
}
In your code:
> function GetActive () {
> if (document.activeElement.id == 'lessonNum') {
> alert('lessonNum is active');
> var b1 = new Boolean(1);
the above line creates a local variable called b1 and assigns a new boolean object. I think you just want a primitive, so:
var b1 = true;
or the whole if..else statement can be replaced with:
var b1 = document.activeElement.id == 'lessonNum';
if (b1) alert('lessonNum is active');
Note that getActive is never called so b1 is never set anyway.
In keyDownTextField you have:
> if(b1==0) {
> alert('a has been pressed');
however b is local to GetActive so a reference error will be thrown. The simple solution is to make b global, a little more work but better though to hold it in a closure.
e.g.
(function(global) {
var b1;
var getActive = function () {
b1 = document.activeElement && document.activeElement.id == 'lessonNum';
if (b1) alert('lessonNum is active');
}
global.getActive = getActive;
var keyDownTextField = function (e) {
e = e || window.event;
var keyCode = e.keyCode || e.which;
if (keyCode == 65) {
getActive(); // should it be called here?
if (b1) {
alert('a has been pressed');
document.getElementById('A').click();
}
}
}
global.keyDownTextField = keyDownTextField;
}(this));
window.onload = function() {
addEvent(document, 'keydown', keyDownTextField);
};
// Just a helper
function addEvent(el, evt, fn){
if (el.addEventListener) {
el.addEventListener(evt, fn, false);
} else if (el.attachEvent) {
el.attachEvent('on' + evt, fn);
}
}

Clearing setTimeout issues

I'm trying to set "mouseactive" to true less than a second after a key command, but I would like to cancel that action if the key is pressed within that time period. However I can't seem to figure out how to do this. This is what I have...
$(window).keydown(function(e) {
if (e.keyCode == 40) {
e.preventDefault();
mouseactive = false;
clearTimeout(t);
var t = setTimeout("mouseActive()",800);
} else if (e.keyCode == 38) {
e.preventDefault();
mouseactive = false;
clearTimeout(t);
var t = setTimeout("mouseActive()",800);
}
});
function mouseActive() {
mouseactive = true;
}
But this doesn't work, it doesn't set mouseactive back to true... can anyone tell me what I'm doing wrong here?
Edit: Cleaned up redundant code.
More Edits: Make sure your var t is defined outside any closure including $(document).ready. See below,
var t = null;
$(document).ready(function () {
//..below code except for var t = null
});
Declare var t outside the handler.
var t = null;
$(window).keydown(function(e) {
e.preventDefault();
if (e.keyCode == 40) {
mouseactive = false;
} else if (e.keyCode == 38) {
mouseactive = false;
}
if (t != null) clearTimeout(t);
t = setTimeout(mouseActive, 800);
});
function mouseActive() {
mouseactive = true;
}
Your problem is that t is not in scope the 2nd time the function runs. You need to make t a global variable .
var t;
$(window).keydown(function(e) {
if (e.keyCode == 40) {
e.preventDefault();
mouseactive = false;
clearTimeout(t);
t = setTimeout(mouseActive,800);
} else if (e.keyCode == 38) {
e.preventDefault();
mouseactive = false;
clearTimeout(t);
t = setTimeout(mouseActive,800);
}
});
function mouseActive() {
mouseactive = true;
}
P.S. Don't pass strings to setTimeout, pass functions. It uses eval when you pass strings.
you are redeclaring "t" all the time, try this:
var t = null;
$(window).keydown(function(e) {
if (e.keyCode == 40) {
e.preventDefault();
mouseactive = false;
if(t != null)
{
clearTimeout(t);
}
t = setTimeout("mouseActive()",800);
} else if (e.keyCode == 38) {
e.preventDefault();
mouseactive = false;
if(t != null)
{
clearTimeout(t);
}
t = setTimeout("mouseActive()",800);
}
});
function mouseActive() {
mouseactive = true;
}

Categories

Resources