I'm pretty new to JS, so I could have made some sort of silly error, but my keylogger doesn't seem to be functioning correctly. It accepts multiple keystrokes correctly, but when one is released, it recognizes both as up. Any help?
Here is my code:
var keymap = {};
onkeydown = onkeyup = function(e){
keymap[e.keyCode] = e.type == 'keydown';
if(keymap[39] && keymap[32]){ // Right+Space
jumpRight();
}
if(keymap[37] && keymap[32]){ // Left+Space
jumpLeft();
}
if(keymap[32]){ // Space
jump();
}
if(keymap[39]){ // Right
right();
}
if(keymap[37]){ // Left
left();
}
}
I'm using Google Chrome, if that helps any.
Thanks!
I think it's recognizing keystrokes correctly, because the array is being updated correctly. The problem is that your functions (left(), right(), jump(), etc.) are only firing when a keypress event happens. When you hold down a key, sometimes it will keep firing keydown events, and sometimes it won't. This causes the functions not to fire, even though your program knows that the key is being held down.
Working example (shows the array values all the time, not just on keypresses; shown array value doesn't necessarily mean the function fires):
var keymap = {};
onkeydown = onkeyup = function(e){
keymap[e.keyCode] = e.type == 'keydown';
if(keymap[39] && keymap[32]){ // Right+Space
jumpRight();
}
if(keymap[37] && keymap[32]){ // Left+Space
jumpLeft();
}
if(keymap[32]){ // Space
jump();
}
if(keymap[39]){ // Right
right();
}
if(keymap[37]){ // Left
left();
}
}
document.onkeydown=onkeydown;
document.onkeyup=onkeyup;
function jump(){}
function left(){}
function right(){}
function jumpLeft(){}
function jumpRight(){}
setInterval(function(){console.log(keymap[37]," ",keymap[32]," ",keymap[39]);},5);
Nonworking example (how it is right now, shows array values only on keypresses; shown array value == function fires):
var keymap = {};
onkeydown = onkeyup = function(e){
keymap[e.keyCode] = e.type == 'keydown';
if(keymap[39] && keymap[32]){ // Right+Space
jumpRight();
}
if(keymap[37] && keymap[32]){ // Left+Space
jumpLeft();
}
if(keymap[32]){ // Space
jump();
}
if(keymap[39]){ // Right
right();
}
if(keymap[37]){ // Left
left();
}
}
document.onkeydown=onkeydown;
document.onkeyup=onkeyup;
function jump(){console.log("jump");}
function left(){console.log("left");}
function right(){console.log("right");}
function jumpLeft(){console.log("jumpleft");}
function jumpRight(){console.log("jumpright");}
Note how in the nonworking example, the logging only happens on keydown events, which is when your functions will be called. In the "working" example, the logging happens regardless of key events, but your functions will still fail to fire, since they still happen when key events do. Here's a fully working example:
var keymap = {};
onkeydown = onkeyup = function(e){
keymap[e.keyCode] = e.type == 'keydown';
}
document.onkeydown=onkeydown;
document.onkeyup=onkeyup;
function jump(){console.log("jump");}
function left(){console.log("left");}
function right(){console.log("right");}
function jumpLeft(){console.log("jumpleft");}
function jumpRight(){console.log("jumpright");}
function main(){
if(keymap[39] && keymap[32]){ // Right+Space
jumpRight();
}
if(keymap[37] && keymap[32]){ // Left+Space
jumpLeft();
}
if(keymap[32]){ // Space
jump();
}
if(keymap[39]){ // Right
right();
}
if(keymap[37]){ // Left
left();
}
}
setInterval(main,250);
Hope this helps!
Good luck learning more JS!
P.S.: You labeled left() as "space". :P
Related
I have two functions that have if statements inside them. I am trying to choose which function to run based off which keys are pressed. When ran the keys without shift override the shift if statements. I am sure to solve this an event handler should be used. However I am not sure where to even start. If the standard ifs are taken out the shift if statements work and vice versa.
Individually each function works as intended. I have looked into adding an event handler based off what is pressed which function overrides which. I have looked at Event Handing and not really sure where to begin.
var map = {};
onkeydown = onkeyup = function(e){
e = e || event; //deals with IE Compatibility
map[e.key] = e.type == 'keydown';
}
I have an array that maps the keys that are pressed since there are more than one key that can be pressed at a specific time.
document.onkeydown = function (e){
if(e.which == 16 && e.which == 117){ //ShiftF6
try {
document.querySelectorAll("input[value=Close]")[0].click();
console.log("Button clicked.");
} catch(ex) {
};
try {
// eslint-disable-line prefer-template
document.querySelectorAll("textarea[name=bugnote_text]")[0].value = //display text
document.querySelectorAll("input[value='Close Ticket']")[0].click();
console.log("Button clicked.");
} catch(ex) {
};
}
This is an example of what is being done with shift and a simple function key.
document.onkeydown = function(zEvent){
if(zEvent.which == 117){ //F6
try {
document.querySelectorAll("input[value=Close]")[0].click();
console.log("Button clicked.");
} catch(ex) {
};
try {
// eslint-disable-line prefer-template
document.querySelectorAll("textarea[name=bugnote_text]")[0].value = //Display text;
document.querySelectorAll("input[value='Close Ticket']")[0].click();
console.log("Button clicked.");
} catch(ex) {
};
}
This is just a single button press.
Note there are multiple if statements inside each function no more than 5 in each however. I know placing these statements in a switch or array would probably be cleaner. I am trying to just decide which function to work out of depending which buttons are being pressed. I am not sure where to begin to get it to choose which way to go.
I have a focus handler on a textfield:
$("#input").on("focus", (e) => {
// do some stuff
});
When I right-click, however, I don't want that focus handler to be executed, so I did:
$("#input").on("mousedown", (e) => {
if (e.button === 2) { // right click
e.preventDefault();
}
});
However, that also prevents the textfield from ever getting focus when I right-click. I still want it to get focus, I just don't want the handler to execute, so I triggered the handler manually:
$("#input").on("mousedown", (e) => {
if (e.button === 2) { // right click
e.preventDefault();
$("#input").trigger("focus", true);
}
});
$("input").on("focus", (e, someParam) => {
if (someParam) return;
// do some stuff
});
This way, the textfield gets focus, but we immediately return out of the handler.
The problem I noticed is that the first time I trigger the focus handler, someParam is undefined and we end up executing do some stuff. For all subsequent right-clicks, someParam is true.
I commented out the line that triggers the focus handler, and indeed, the focus handler is never executed, because we call preventDefault, so it seems that the first execution of the handler necessarily comes from $("#input").trigger("focus", true);. So why then is someParam undefined if I'm passing in true as the extra parameter?
JsFiddle. Tested in Chrome.
This appears to be a current issue with jQuery. See this github issue.
As a workaround, try the following:
var a = $("#a");
var _focusData = null;
var focusEvent = (e) => {
if (_focusData) {
_focusData = null;
return;
}
_focusData = null;
var t = $("textarea").first();
t.val(t.val() + "\nfocus");
};
a.on("mousedown", (e) => {
if (e.button === 2) {
e.preventDefault();
var t = $("textarea").first();
t.val(t.val() + "\n" + e.button);
_focusData = true;
a.trigger("focus");
}
});
a.on("focus", focusEvent);
After doing a lot more research, including trying to trigger custom events with $.Event, it seems like your best course of action is to either use stack traces, pollute the global scope, or downgrade your jQuery version.
I found another solution besides the comment from CBroe (to just perform the logic in an else statement):
Use a named function as our mouse down handler, then examine the stack trace.
var a = $("#a");
a.on("mousedown", onMouseDown);
function onMouseDown(e) {
if (e.button === 2) {
e.preventDefault();
e.stopImmediatePropagation()
var t = $("textarea").first();
t.val(t.val() + "\n" + e.button);
a.trigger("focus", true);
}
}
a.on("focus", (e, someParam) => {
var stackTrace = getStackTrace();
if(stackTrace.indexOf("onMouseDown") >= 0) return;
var t = $("textarea").first();
t.val(t.val() + "\nfocus");
console.log(someParam);
console.trace();
});
var getStackTrace = function() {
var obj = {};
if(Error.captureStackTrace) { //Chrome (IE/Edge? Didn't test)
Error.captureStackTrace(obj, getStackTrace);
}
else { //Firefox
obj = Error();
}
return obj.stack;
};
https://jsfiddle.net/bjj56eua/4/
As I was typing this up, FrankerZ posted an answer which looks much nicer. I suggest doing that. This was a dirty hack involving string parsing, but it works. It just isn't a good idea.
I'm trying to create a Multi-player game using JS.
function EvilBall(player,color)
{
EvilCircle.call(this,this.size,this.velY,this.velX);
this.color=color;
this.score =0;
this.player=player;
}
EvilBall.prototype=Object.create(EvilCircle.prototype);
EvilBall.prototype.constructor =EvilBall;
EvilBall.prototype.setControls=function(left,right,down,up){
var _this = this;
window.onkeydown = function(e) {
console.log(e.keyCode);
if (e.keyCode === left) {
_this.x -= _this.velX;
} else if (e.keyCode === right) {
_this.x += _this.velX;
} else if (e.keyCode === down) {
_this.y -= _this.velY;
} else if (e.keyCode === up) {
_this.y += _this.velY;
}
}
}
after this I'm creating two instances of EvilBall and setting there controls using setControls function which has event handler function inside.
var evilBall = new EvilBall('p1','white');
var evilBall2 = new EvilBall('p2','yellow');
evilBall2.setControls(65,68,87,83);
evilBall.setControls(37,39,38,40);
Only evilBall instance with key 37,39,38 and 40 is working when keys are pressed. I have figured that since evilBall is mentioned below evilBall2, it is working fine. If an event handler is working fine on one instance, why is not working on the other?
How can we develop multi-player games in JS when event-handler on only one instance works?
Can anyone please explain this to me. Am I missing something here?
Window onkeydown is a property:
window.onkeydown = ()=>alert("one");
window.onkeydown = ()=>alert("two");//will override the first
window.onkeydown();
So use window.addEventListner instead:
window.addEventListener("keydown",function(event){
...
});
Overall it might be better to just have one event listener:
var keylisteners=[];
window.onkeydown=function(e){
(keylisteners.find(el=>el.key==e.keyCode)||{callback:function(){}}).callback();
};
Use like this:
keylisteners.push({
key:42,
callback:function(){}
});
By the way, your shape function doesnt take arguments:
Shape.call(this); //will do the job too
How can I clarify ALT+CTRL and ALTGR key press?
I found this code here as possible solution, but it's doesn't work:
if (event.ctrlKey && event.altKey) {
}
This code is true for alt+ctr and for altGr as well.
I have situation like this: for alt+ctrl+e (for example e, it's no matter) I want one thing and for altGr+e another, how can I do this?
If anyone have some idea, please tell me.
You can detect which key is pressed (from right key or left key) by value of location property in event object. If value of location property is 1 (e.location=1) then left key is pressed. if value is 2 then right key is pressed.
Here I have providing my code for RightAlter+RightCtrl+<any_valid_key>
Check this Example
var isRightAltKey=false;
var isRightCtrlKey=false;
var validKeys=['a','s','d','f','g']; //keep empty array if no need to check key
document.addEventListener("keydown", function(e) {
if(e.key=="Alt"){
// when right Alter pressed make isRightAltKey true
isRightAltKey= (e.location==2);
}
else if(e.key=="Control"){
// when right Control pressed make isRightCtrlKey true,
//if you need any ctrl key pressed then simply set isRightCtrlKey= true;
isRightCtrlKey= (e.location==2);
}
// checking both right key is pressed already or not?
var isRightKeys= isRightAltKey && isRightCtrlKey;
// validate other keys [optional]
var isValidKey=((typeof validKeys === "undefined") || validKeys.length==0 || validKeys.indexOf(e.key.toLowerCase())>=0);
if (isRightKeys && isValidKey){
document.getElementById("detect_key").innerHTML = "RightAlt + RightCtrl + "+e.key;
}
else
{
document.getElementById("detect_key").innerHTML="";
}
}, false);
document.addEventListener("keyup", function(e) {
if(e.key=="Alt"){
// when right Alter released make isRightAltKey false
isRightAltKey= false;
}
else if(e.key=="Control"){
// when right Control released make isRightCtrlKey false
isRightCtrlKey= false;
}
}, false);
<div id="detect_key"></div>
Why attached keyup event listner?
Here we have to detect key location when Ctrl and Alt key is pressed (on keydown event). and we have to store it in flag variable and make it true. when key is released (on keyup event) have to mark as false. Otherwise those flags always remain true. on Next key press it will always true
You can use the location to determined which alt is being pressed.
In order to support Alt+Ctrl we'll save the last location of the pressed Alt.
Location = 1 // Left
Location = 2 // Right
Then, once both Alt and Ctrl are pressed, do your thing. In this example, we'll just write the Alt side in the result div. You can add the "e" pressed condition as well:
if (e.ctrlKey && e.altKey && e.key == "e"){
Example
HTML
<div class="cont">
Click Alt + Ctrl<br /><br />
<div id="res"></div>
</div>
Javascript
var lastAltLocation;
document.addEventListener("keydown", function(e) {
if (e.key == "Alt"){
lastAltLocation = e.location;
}
if (e.ctrlKey && e.altKey){
if (lastAltLocation == 1){
document.getElementById("res").innerHTML = "Left";
}
if (lastAltLocation == 2){
document.getElementById("res").innerHTML = "Right";
}
}
}, false);
Sticking strictly to your question here are the codes for both the required cases:
document.addEventListener ("keydown", function (zEvent) {
if (zEvent.altKey && zEvent.code === "KeyE") {
if(zEvent.ctrlKey) {
//Do Ctrl+Alt+E Stuff Here.
} else {
//Do Alt+E Stuff Here.
}
});
Now breaking down the things going on here. keydown allows you to detect multiple keypresses.
First we check if the Alt and E keys are pressed. If yes, we then go on to check in the Ctrl key is also active and take the appropriate action as needed.
Good day all.
I'm having some problems with hoverintent.js a jquery plugin that handle the mouseOver events in a different way than normal.
Due to some complications, I can't modifiy anything but the js of this plugin, but I need to make it compliant with touch events and not only with mouseOver and mouseLeave.
after some debugs, I have managed to recognize this part of the code to be the one to modify:
var handleHover = function(e) {
// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
if ( p == this ) { return false; }
// copy objects to be passed into t (required for event object to be passed in IE)
var ev = jQuery.extend({},e);
var ob = this;
// cancel hoverIntent timer if it exists
if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
// else e.type == "onmouseover"
if (e.type == "mouseover") {
// set "previous" X and Y position based on initial entry point
pX = ev.pageX; pY = ev.pageY;
// update "current" X and Y position based on mousemove
$(ob).bind("mousemove",track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
// else e.type == "onmouseout"
} else {
// unbind expensive mousemove event
$(ob).unbind("mousemove",track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
}
}
};
// bind the function to the two event listeners
return this.mouseover(handleHover).mouseout(handleHover);
what I've done so far is to make the function working different with mobiles:
var handleHover = function(e) {
isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
if(isMobile){
console.log("Ismobile");
}else{
... Same code as before here ...
}
// bind the function to the two event listeners
return this.mouseover(handleHover).mouseout(handleHover);
and now i'm struck. I would like it to "change" its behavior to handle the touch, and not the mouse over event, so on mobiles I will need to touch the element, instead to hovering on it. May someone give me an help? Am I on the right way? Is it the right way to think of it?
unluckily I have only the possibility to change this file and some few more.
Recently i bumped into several problems with changing hoverIntent.js, and ended up in writing my own plugin: hoverDelay.js (much simpler, and less code). see if you can use it, and modify it to your own needs (and maybe contribute the mobile code to it :-)