Javascript Lookup table vs else if and multiple matching results - javascript

I'm creating a canvas game for fun, and I'm trying to re-factor some of my multiple else if statements to use object lookup tables instead.
This is my current code for assigning variable values on keydown:
function keyDown(e) {
keypressed = true;
if (e.keyCode == 39 || e.keyCode == 68) {rightKey = true; }
else if (e.keyCode == 37 || e.keyCode == 65) {leftKey = true;}
else if (e.keyCode == 38 || e.keyCode == 87) {upKey = true; }
else if (e.keyCode == 40 || e.keyCode == 83) {downKey = true; }
else if (e.keyCode == 80) { isPaused = !isPaused; document.body.classList.toggle('pause'); }
if (e.keyCode === 69) { startHit(); }
}
I want to assign both wsad keys and the arrow keys to do the same thing, thus the use of || in the if conditions.
I read that using an object literal lookup table is a faster way to achieve this and this is my attempt:
var codes = {
39 : function() {
return rightKey = true;
},
37 : function() {
return leftKey = true;
},
38 : function() {
return upKey = true;
},
40 : function() {
return downKey = true;
},
80 : function() {
isPaued = !isPaused;
document.body.classList.toggle('pause');
},
69 : startHit
}
codes[68] = codes[39];
codes[65] = codes[37];
codes[87] = codes[38];
codes[83] = codes[40];
function keyDown(e) {
keypressed = true;
codes[e.keyCode]();
}
This works just fine, but I'm not sure the assignment of the bottom keys is the best way to do this? I can't obviously use the || operator in the left hand assignment, so would there be a cleaner way to do this or should I just stick with the else ifs?
Also, I know I could use a switch statement, but I feel like it would look similar to the way I've done above.
Any advice would be great. Thanks.

Why not use a switch statement?
function keyDown(e) {
keypressed = true;
switch (e.keyCode) {
case 39:
case 68:
rightKey = true;
break;
case 37:
case 65:
leftKey = true;
break;
case 38:
case 87:
upKey = true;
break;
case 40:
case 83:
downKey = true;
break;
case 80:
isPaused = !isPaused;
document.body.classList.toggle('pause');
break;
case 69:
startHit();
}
}

what about this?
var codes = function (){
function rightKey(){
rightKey = true;
}
function leftKey() {
leftKey = true;
}
return {
39 : rightKey,
37 : leftKey,
'...': '...',
68 : rightKey,
65 : leftKey
}}()

Related

How can I hit multiple html buttons at once in javascript?

I can click the arrow buttons on the web page, but multiple buttons cannot be read at the same time.If I click on 37 and 39 keys it does not work but only when I click on 37 keys it works. Same goes for other keys, how can I control more than one button at the same time?
const handleArrowButtonMouseDown = function() {
$('button').on('mousedown touchstart', (e) => {
e.preventDefault();
if(state.arrowPressed) return;
let direction = $(e.target).closest('button').attr('id');
state.setArrowPressed(direction);
state.setRobotCommand();
});
};
const handleArrowButtonMouseUp = function() {
$('button').on('mouseup mouseleave touchend', endCurrentOperation);
};
const handleArrowKeyDown = function() {
$(document).keydown((e) => {
if(state.arrowPressed) return;
switch(e.which) {
case 37:
state.setArrowPressed('left');
break;
case 38:
state.setArrowPressed('up');
break;
case 39:
state.setArrowPressed('right');
break;
case 40: // down
state.setArrowPressed('down');
break;
default: return;
}
e.preventDefault();
state.setRobotCommand();
});
};
const handleArrowKeyUp = function() {
$(document).keyup((e) => {
if (e.which === 37 && state.arrowPressed !== 'left') return;
if (e.which === 38 && state.arrowPressed !== 'up') return;
if (e.which === 39 && state.arrowPressed !== 'right') return;
if (e.which === 40 && state.arrowPressed !== 'down') return;
endCurrentOperation();
});
};
There is one way, but it's not safe to rely on, since you cannot detect if a key is currently down in JavaScript.
The example below works only with Shift + Number. It's closest to achieve when both keys are pressed.
window.addEventListener("keydown", function (event) {
if (event.shiftKey) {
if (/\d/.test(event.code)){
console.log("SHIFTKEY + Number:"+event.code);
}
}
}, true)
Maybe you can repeat the same login to your code.

cancel an if statement if another statement comes true

I have this function that plays different sounds to different keys. But if I press a key, then press another key right away, the previous sound will still play.
My question is, how do I cancel the previous sound when a new one is played?
Here's the code:
window.addEventListener("keydown", checkKeyPressed, false);
function checkKeyPressed(evt) {
if (evt.keyCode == "81") { //q
document.getElementById('enklyd').play();
}
if (evt.keyCode == "87") { //w
document.getElementById('lyd1').play();
}
if (evt.keyCode == "69") { //e
document.getElementById('lyd2').play();
}
if (evt.keyCode == "82") { //r
document.getElementById('lyd3').play();
}
if (evt.keyCode == "84") { //t
document.getElementById('lyd4').play();
}
if (evt.keyCode == "89") { //y
document.getElementById('lyd5').play();
}
}
This isn't really a matter of "stopping" the if statement because they are individually doing their job correctly. What you want to stop is the sound clip being played.
For this you can use the .pause() method, set the .currentTime to 0, or I believe you can also set the volume to 0 and just let it play out.
As mentioned in a comment, there are a few SO questions that may have already answered this. Is there a unique situation that isn't being answered in those?
I think this works for you:
var e = document.getElementById('enklyd');
function checkKeyPressed(evt) {
if (evt.keyCode == "81") { //q
e.pause();
e.currentTime = 0;
e = document.getElementById('enklyd');
e.play();
}
if (evt.keyCode == "87") { //w
e.pause();
e.currentTime = 0;
e = document.getElementById('lyd1');
e.play();
}
if (evt.keyCode == "69") { //e
e.pause();
e.currentTime = 0;
e = document.getElementById('lyd2');
e.play();
}
if (evt.keyCode == "82") { //r
e.pause();
e.currentTime = 0;
e = document.getElementById('lyd3');
e.play();
}
if (evt.keyCode == "84") { //t
e.pause();
e.currentTime = 0;
e = document.getElementById('lyd4');
e.play();
}
if (evt.keyCode == "89") { //y
e.pause();
e.currentTime = 0;
e = document.getElementById('lyd5');
e.play();
}
}
Actually, the issue is not regarding the if condition. But you can try the following code, I think this will work fine for you.
window.addEventListener("keydown", checkKeyPressed, false);
var keyMap = {
"81": "enklyd", //q
"87": "lyd1", //w
"69": "lyd2", //e
"82": "lyd3", //r
"84": "lyd4", //t
"89": "lyd5", //y
};
var prevPlayed = null, target = null, prevTarget = null;
function checkKeyPressed(evt) {
prevTarget = document.getElementById(keyMap[prevPlayed])
target = document.getElementById(keyMap[evt.keyCode]);
if (prevPlayed !== null && prevTarget !== null)
prevTarget.pause();
if (keyMap[evt.keyCode] && target !== null) {
target.currentTime = 0;
target.play();
}
prevPlayed = evt.keyCode;
}
You should use 'switch' instead of using 'if'.Just add a common class to all your elements
const yourDiv = document.querySelector('yourDiv');
window.addEventListener("keydown", checkKeyPressed, false);
function checkKeyPressed(evt) {
yourDiv.currentTime = 0;
switch(evt) {
case '81':
document.getElementById('enklyd').play();
break;
case '87' :
document.getElementById('lyd1').play();
break;
case '69' :
document.getElementById('lyd2').play();
break;
case '82' :
document.getElementById('lyd3').play();
break;
case '84' :
document.getElementById('lyd4').play();
break;
case '89' :
document.getElementById('lyd5').play();
break;
default :
return null;
}
}

How to restrict keyboard key events in web application?

I am doing the secured web application. My client requirement is to don't allow the application to refresh using the F5 .
Also to restrict events of the Esc , Backspace keys.
I am using the jQuery 1.9.1.
My code is given below.
I can get the alert, but if I press the F5 button my page gets refreshed. I don't know why?
BackSpace also going back to the previous page.
$(document).on('keydown' , function(event) {
switch (event.keyCode) {
case 116 : // 'F5'
alert("116 :"+event.keyCode);
event.preventDefault();
event.returnValue = false;
event.keyCode = 0;;
break;
case 27: // 'Esc'
alert("27 :"+event.keyCode);
event.preventDefault();
event.returnValue = false;
break;
case 08: // 'BackSpace'
if (event.srcElement.tagName == "INPUT"
|| event.srcElement.tagName == "TEXTAREA") {
} else {
event.preventDefault();
event.returnValue = false;
event.keyCode = 0;
}
break;
}
});
Can any one point out me where I made a mistake ?
Look here. Try to enter something into input box and try 'f5', 'esc' and 'backspace' keys on frame. It works in jsFiddle under Mac Chrome browser, it should work on your browser also. When you preventing your event you should call stopProagation function. Moreover, when you calling srcElement you should call original events by event.originalEvent.srcElement because normalised jquery event doesn't contain srcElement property. In console it gives undefined property error. Also you have error like following event.keyCode = 0;*;*
$(document).on('keydown' , function(event) {
switch (event.keyCode) {
case 116 : // 'F5'
alert("116 :"+event.keyCode);
event.preventDefault();
event.stopPropagation();
console.log('hello');
break;
case 27: // 'Esc'
alert("27 :"+event.keyCode);
event.preventDefault();
event.stopPropagation();
break;
case 08: // 'BackSpace'
if (event.originalEvent.srcElement.tagName == "INPUT"
|| event.originalEvent.srcElement.tagName == "TEXTAREA") {
alert("27 :"+event.keyCode);
event.preventDefault();
event.stopPropagation();
} else {
alert("27 :"+event.keyCode);
event.preventDefault();
event.stopPropagation();
}
break;
}
});
Here is my solution ,
var x;
var isIE;
var e;
var code;
var ElementType;
document.onkeydown = whichkey;
function whichkey(e) {
isIE = (document.all ? true : false);
if (navigator.appName == "Microsoft Internet Explorer") {
switch (event.keyCode) {
case 112: //f1 button
if (isIE) {
document.onhelp = function() {
return (false);
};
window.onhelp = function() {
return (false);
};
}
event.returnValue = false;
event.keyCode = 0;
return false;
case 82: //R button
if (event.ctrlKey) {
event.returnValue = false;
event.keyCode = 0;
return false;
}
else {
return true;
}
case 113: //f2 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 114: //f3 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 115: //f4 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 116: //f5 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 117: //f6 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 118: //f7 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 119: //f8 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 120: //f9 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 121: //f10 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 123: //f12 button
event.returnValue = false;
event.keyCode = 0;
return false;
case 8: //Backspace button
if (event.srcElement.tagName == "INPUT" || event.srcElement.tagName == "TEXTAREA") {
return true;
}
else {
return false;
}
}
}
else {
if (!e)
e = window.event;
if (e.keyCode)
code = e.keyCode;
else if (e.which)
code = e.which;
if (code == 112) {
//f1 button
return false;
}
if (code == 8) { // 'BS'
ElementType = e.srcElement || e.target;
if (ElementType.tagName == "INPUT" || ElementType.tagName == "TEXTAREA") {
return true;
}
else {
return false;
}
}
if (code == 113) {
//f2 button
return false;
}
if (code == 114) {
//f3 button
return false;
}
if (code == 115) {
//f4 button
if (event.altKey) {
return false;
}
else {
return false;
}
}
if (code == 116) {
//f5 button
return false;
}
if (code == 117) {
//f6 button
return false;
}
if (code == 118) {
//f7 button
return false;
}
if (code == 119) {
//f8 button
return false;
}
if (code == 120) {
//f9 button
return false;
}
if (code == 121) {
//f10 button
return false;
}
if (code == 123) {
//f12 button
return false;
}
if (code == 18) {
//altf4 button
return false;
}
if (code == 82) {
//R button
if (event.ctrlKey) {
return false;
}
else {
return true;
}
}
if (event.altKey && event.keyCode == 115) // disable alt+f4
{
event.keyCode = 0;
event.cancelBubble = true;
return false;
}
}
}

Javascript error: I have a unexpected end of input on my first line, with no apparent problems, but I'm getting a message and the whole canvas stops

I put in the entire thing just in case
I went into chrome and looked for errors, and it wasnt working either so I checked, apparently the first line has a problem. I kept the first 6 lines and deleted all else then it worked fine, so I went to SublimeText2 and searched for every ) and } in the code.
var canvasBg = document.getElementById('canvasBg');
var ctxBg = canvasBg.getContext('2d');
var canvasJet = document.getElementById('canvasJet');
var ctxJet = canvasJet.getContext('2d');
var jet1;
var fps = 17;
var drawInterval;
var imgSprite = new Image();
imgSprite.src = 'SpriteSheet.png'
imgSprite.addEventListener('load',init,false);
function init() {
drawBg();
startDrawing();
jet1 = new Jet();
document.addEventListener('keydown',checkKeyDown,false);
document.addEventListener('keyup',checKeyUp,false);
}
function draw() {
jet1.draw();
}
function startDrawing() {
stopDrawing();
drawInterval = setInterval(draw,fps);
}
function stopDrawing() {
clearInterval(setInterval);
}
Jet.prototype.draw = function() {
clearCtxJet();
ctxJet.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
};
function Jet() {
this.srcX = 0;
this.srcY = 0;
this.drawX = 200;
this.drawY = 200;
this.width = 96;
this.height = 30;
}
function drawJet() {
}
function drawBg() {
ctxBg.drawImage(imgSprite,96,0,800,500,0,0,800,500)
}
function clearCtxBg() {
ctxBg.clearRect(0,0,800,500);
}
function clearCtxJet() {
ctxJet.clearRect(0,0,800,500);
}
function checkKeyDown(e) {
var keyID = (e.keyCode) ? e.keyCode : e.which;
if (keyID === 38) { // 38 is up key
alert('up arrow was pressed');
e.preventDeafault();
}
if (keyID === 39) { // 39 is right key
e.preventDeafault();
}
if (keyID === 40) { // 40 is down key
e.preventDeafault();
}
if (keyID === 37) { // 37 is left key
e.preventDeafault();
}
function checkKeyup(e) {
var keyID = (e.keyCode) ? e.keyCode : e.which;
if (keyID === 38) { // 38 is up key
alert('up arrow was pressed');
e.preventDeafault();
}
if (keyID === 39) { // 39 is right key
e.preventDeafault();
}
if (keyID === 40) { // 40 is down key
e.preventDeafault();
}
if (keyID === 37) { // 37 is left key
e.preventDeafault();
}
}
I assume you're showing only parts of the code so there's no way of knowing whether this is the actual error, but both checkKeyup and checkKeydown are missing closing braces.
I recommend installing Package Control for Sublime Text 2 and then using it to install SublimeLinter which will be able to check your code for you and point out missing semicolons and braces.
It would be nice to see full code in http://jsfiddle.net

Too many if-else statements. Can they be made global?

I'm trying to streamline this script. I have 50 of these if e.keyCode statements, so double nesting if/else statements seems ridiculous, but all other attempts I've made haven't worked.
The first if/else statement if(e.keyCode == 66 && e.shiftKey) is necessary, but I'm not sure about the second if (typedAdjusted >= paperWidth % charWidth) which is throwing a warning if too many characters are typed on a line relative to a fixed width.
Can the functionality if (typedAdjusted >= paperWidth % charWidth) gives me be global? It will need to be checked against specific keyCodes. For instance, the letter "B" should be figured into typedAdjusted while BACKSPACE and TAB and COMMAND should not.
var typed = $("span.char").length;
var typedAdjusted = typed+1;
var paperWidth = 900;
var charWidth = 44;
if (e.keyCode == 66) {
if (e.keyCode == 66 && e.shiftKey) {
$('#charLine-1').append('<span class="char">B</span>');
if (typedAdjusted >= paperWidth % charWidth) {
$('body').append('<span id="warning">WARNING!</span>');
}
else {
return false;
}
}
else {
$('#charLine-1').append('<span class="char">b</span>');
if (typedAdjusted >= paperWidth % charWidth) {
$('body').append('<span id="warning">WARNING!</span>');
}
else {
return false;
}
}
}
What do you mean by having 50 of them? You... don't mean one for each letter?
And why do you check for the keycode value twice? Do you see that the code is precisely identical except for the character?
Keep a lookup table, or direct character translation, and shorten it to a single method:
var c = lookup(e.keyCode, e.shiftKey);
$('#charLine-1').append('<span class="char">' + c + '</span>');
if (typedAdjusted >= paperWidth % charWidth) {
$('body').append('<span id="warning">WARNING!</span>');
} else {
return false;
}
That's going to create a whole bunch of spans.
var normal = {
66: 'b', 67: 'c', // etc.
};
var shifted = {
66: 'B', 67: 'C', // etc.
};
/**
* Looks up keycode using appropriate map.
*
* Returns `undefined` if not found; shouldn't insert.
*/
function lookup(code, shift) {
return shift ? shifted[code] : normal[code];
}
IF you like checking each one use a switch: call the checkKey function as needed passing the event.
function checklen() {
var typed = $("span.char").length;
var typedAdjusted = typed + 1;
var paperWidth = 900;
var charWidth = 44;
return (typedAdjusted >= paperWidth % charWidth);
}
function checkKey(e) {
var mychar = '';
var checkit = false;
switch (e.keyCode) {
case 66:
mychar = e.shiftKey ? 'B' : 'b';
checkit = checklen();
break;
case 67:
mychar = e.shiftKey ? 'C' : 'c';
checkit = checklen();
break;
case 68:
mychar = e.shiftKey ? 'D' : 'd';
checkit = checklen();
break;
default:
checkit = false;
break;
}
if (!checkit) {
$('#charLine-1').append('<span class="char">' + mychar + '</span>');
}
else {
$('body').append('<span id="warning">WARNING!</span>');
}
}
to get it to work on the entire document:
$(document).ready(function(){
$(document).keydown(function(e) {
checkKey(e);
});
});
then just click on the page and type characters - note only 'b','c','d' on the code above.
If you observe the keypress event, you can use String.fromCharCode(event.keyCode) to get the character entered and not have to mess with a lookup table.
function (event) {
var key = event.keyCode;
if (key > 31 && key < 127) return String.fromCharCode(key);
}

Categories