JavaScript addEventListener click and keycode - javascript

Works with mouse click.
key code does not trigger video stop.
keycode after added focus() works but it can cause some problems.
I want keycode and mouse click to work all the time. Independently of each other, it will click on the button when I press the "space" button and when I click the mouse, it will click on the button.
let testKey = document.querySelector(".switch-btn");
["click", "keypress"].forEach(ev => {
testKey.addEventListener(ev, function(e) {
if(ev == "click") {
console.log("click");
if(!testKey.classList.contains("slide")) {
testKey.classList.add("slide");
} else {
}
}
if(e.keyCode === 32) {
console.log("click, space");
}
});
});
<button class="switch-btn">
<span>
Play
</span>
<span>
pause
</span>
<span class="switch"></span>
</button>

The keypress event is deprecated and no longer recommended (See Document: keypress event documentation). Instead you can use the keydown event.
If your intention is to handle the click and keydown events separately then you should check the detail property for the click event handler. If the button is clicked the property will have a value of 1. (See UIEvent.detail documentation)
Unless the user focuses on the button using the tab key, the keydown event is not going to fire your handler. Adding a handler at the container or document level can overcome this. In the code below I have added such a handler and called the stopPropagation method within the handler on the button to prevent the event bubbling up to the document level.
let testKey = document.querySelector(".switch-btn");
document.addEventListener('keydown', function(e) {
if(e.keyCode === 32) {
console.log("document: space pressed");
doTheClassListThing();
}
});
["click", "keydown"].forEach(ev => {
testKey.addEventListener(ev, function(e) {
if(ev == "click" & e.detail == 1) {
console.log("click");
doTheClassListThing();
}
if(e.keyCode === 32) {
e.stopPropagation();
console.log("Button: space keydown");
doTheClassListThing();
}
});
});
function doTheClassListThing() {
console.log('doTheClassListThing() executed');
if(!testKey.classList.contains("slide")) {
testKey.classList.add("slide");
} else {
}
}
<button class="switch-btn">
<span>
Play
</span>
<span>
pause
</span>
<span class="switch"></span>
</button>

I'm not sure I understand the question, but the reason the key doesn't register initially is because the button isn't focused. You could try calling testKey.focus() to ensure it's initially focused.
I do not recommend this approach--forcing focus on the button could create accessibility issues and interfere with other element interactions, but here's a snippet just to demonstrate how focusing the button resolves the issue.
I agree with Terry's comment below, that attaching event handlers on body would be less fraught.
let testKey = document.querySelector(".switch-btn");
testKey.focus();
["click", "keypress"].forEach(ev => {
testKey.addEventListener(ev, function(e) {
if(ev == "click") {
console.log("click");
if(!testKey.classList.contains("slide")) {
testKey.classList.add("slide");
} else {
}
}
if(e.keyCode === 32) {
console.log("click, space");
}
testKey.focus();
});
});
<button class="switch-btn">
<span>
Play
</span>
<span>
pause
</span>
<span class="switch"></span>
</button>

Related

return a function if there was no click event

I have a function that fires only when we press the spacebar or the isJumping event is already happening
If we press any other key, nothing happens.
function onJump(e) {
if (e.code !== "Space" || isJumping) return
yVelocity = JUMP_SPEED
isJumping = true
}
The question is, can I add to this function so that, in addition to the space, the mouse click event also fires?
That is, if we press the spacebar or click on the mouse, then the function works
The mouse click event is not key code, so I'm a little confused on how to do it right
If the function is called when you press a key then that is because somewhere in the code you didn't show us you have some code which registers that function (or another function which calls the first) as an event handler that triggers when a key is pressed (e.g. keyup or keypress).
If you want to call it when something is clicked then you also need to register it as an event handler for that kind of event (e.g. click or mousedown).
MDN has a tutorial on event handling.
I assume onJump is attached to a keyboard event handler, presumably on document, something like this:
document.addEventListener("keydown", onJump);
If so, you can also attach it to click:
document.addEventListener("keydown", onJump);
document.addEventListener("click", onJump);
...and then modify the function so it checks which type of event it got and handles it accordingly:
function onJump(e) {
if (isJumping || (e.type === "keydown" && e.code !== "Space")) return;
yVelocity = JUMP_SPEED;
isJumping = true;
}
That will only check e.code if the event is the keydown event, not the click event. (Adjust the event name as necessary).
USE EVENT.TYPE
Use the event.type property when using a single handler for multiple events. In your case, you want the same function to handle keyboard and mouse events. View and run the code snippet below to see how it works.
window.addEventListener("keydown", onJump);
window.addEventListener("mousedown", onJump);
const JUMP_SPEED = 100;
let isJumping = false;
function onJump(e) {
if (e.type === "mousedown") {
// add event handler here
}
else if (e.type === "keydown" && e.code === "Space" && !isJumping) {
yVelocity = JUMP_SPEED
isJumping = true
}
console.log("event: " + e.type + ", isJumping: " + isJumping + ", keycode: " + e.code);
}
<h3>Click the mouse or press spacebar</h3>
<img src="https://cdn.icon-icons.com/icons2/567/PNG/512/packman_icon-icons.com_54382.png" style="height:100px;width:auto"/>
You can use a event listener, like this:
document.body.addEventListener('click', function(){
console.log('hi');
});
<body>
<p>This is supposed to be your elements. Click here!</p>
</body>
In your case, you can make it
document.addEventListener("keydown", onJump);
document.addEventListener("click", onJump);
You can change your function correspondingly, so that it works with the event listeners:
function onJump(e) {
if (isJumping || (e.type == "keydown" && e.code !== "space")) return;
yVelocity = JUMP_SPEED;
isJumping = true;
}

on down arrow KeyPress, click event is getting fired

on down arrow keypress , click event is getting fired, event.keycode is undefined
$(".dropdown:not(.li-search) a.dropdown-toggle", ".navbar-collapse").on("click", function(event) {
var target = $(this).attr("target");
if (event.keyCode !== '40'){
if (!$(".li-menu").is(":visible") && target === undefined) {
location.href=this.href;
} else {
window.open(this.href, '_blank');
}
}
});
in this code i am trying to open main menu in new tab , but external link is getting open on down arrow keypress
call preventDefault() function.
$(".dropdown:not(.li-search) a.dropdown-toggle", ".navbar-collapse").on("click", function(event) {
event.preventDefault();
var target = $(this).attr("target");
if(event.keyCode!=='40'){
if (!$(".li-menu").is(":visible") && target===undefined) {
location.href=this.href;
}
else {
window.open(this.href,'_blank');
}
}
});
See the keycode for the reference https://css-tricks.com/snippets/javascript/javascript-keycodes/
in order to configure your app for particular key event
Looking at the classes dropdown-toggle, navbar-collapse, I'm guessing that you are using Bootstrap library.
If that is the case, the behaviour you are seeing is reasonable. Let's break down the issues:
on down arrow keypress , click event is getting fired
Q: You have only bind the handler on click event so why are it is being triggered on keypress?
A: Because this is a feature of bootstrap dropdown. To have better accessibilty, bootstrap triggers click event on the keydown of up, down, esc and space keys.
event.keycode is undefined
Since it is a click event handler and not some keyboard event handler like keydown or keypress, event.keyCode should be undefined
Note: You are using a strict equality in the following condition
if (event.keyCode !== '40')
This will check both the type and value of the operands. Now, event.keyCode always return a Number while '40' is a string, hence the above condtion will yield false even if keyCode is 40. You should correct it to:
if (event.keyCode !== 40)
Now, if you want to stop the redirect on down key, you should check whether the event triggered is an original event or was triggered by some js logic. For this, you may choose jQuery's event.isTrigger or event.originalEvent
Here's a code snippet:
$(".dropdown:not(.li-search) a.dropdown-toggle", ".navbar-collapse").on("click", function(event) {
var target = $(this).attr("target");
// Check if NOT an triggered event
if (!event.isTrigger) {
if (!$(".li-menu").is(":visible") && target === undefined) {
location.href = this.href;
} else {
window.open(this.href, '_blank');
}
}
});
<a> tags will fire the click event when you press enter on them. However you will not have a keyCode on the event because it is not a Key* event. If you want to know the keyCode add a keyDown or keyUp handler as well. You could also handle both by doing something like the following:
$(".dropdown:not(.li-search) a.dropdown-toggle", ".navbar-collapse").on("click keydown", function(event) {
var target = $(this).attr("target");
if(event.type === 'keydown' && event.keyCode!=='40'){
if (!$(".li-menu").is(":visible") && target===undefined) {
location.href=this.href;
}
else {
window.open(this.href,'_blank');
}
}
});
You'll probably also want to add an event.preventDefault(); in there if you wish to prevent default browser behaviour from taking place.

Use a preventdefault to get out of the loop after pressing Enter key

This is a complete revision of my initial question, all unnecessary resources and references were deleted
I am tying the same event listener to 2 different elements: a button and Enter key, and it looks like the following:
var funcelement = function(){
//function code
};
$('#buttonID').click(funcelement);
$('#inputID').keyup(function () {
if (event.which == 13) {
$('#buttonID').trigger('click');
}
})
What I am trying to do is to prevent propagation of the enter key press if focus is on the submit button(#buttonID) by using preventDefault().
So I tried various combinations to make it work. The following is the latest result on my attempts
$('#inputID').keyup(function () {
var hasfocus = $('#buttonID').is(':focus') || false;
if (event.which == 13) {
if (!hasfocus) {
event.preventDefault();
$('#buttonID').trigger('click');
//hasfocus = true;
}
else {
//event.preventDefault();
//$('#buttonID').trigger('click');
}
}
})
After I enter a text into an input box and press Enter key, a confirmation window with yes/cancel buttons pops up with focus on yes button. Once I press Enter again, another window confirming that changes were made pops up with Ok button focused on it. Once I press Enter again, everything I need is being made.
However, there is one problem: after the last step is done, I am going back to the if (!hasfocus) line.
How do I prevent that from happening? Once the stuff I need is done - I don't want to go into that line again.
You can pass a parameter to into the function and stop the propagation there like so:
var funcelement = function(event, wasTriggeredByEnterKey){
if (wasTriggeredByEnterKey && $('#buttonID').is(':focus')) {
event.stopPropagation;
}
//function code
};
$('#buttonID').click(funcelement);
$('#inputID').keyup(function () {
if (event.which == 13) {
$('#buttonID').trigger('click', [true]);
}
}
)
UPDATE
In order to answer your revised issue, you should use the "keydown" event rather than "keyup" when working with alerts. This is because alerts close with the "keydown" event but then you are still triggering the "keyup" event when you release the enter key. Simply change the one word like this:
$('#inputID').keydown(function () {
var hasfocus = $('#buttonID').is(':focus') || false;
if (event.which == 13) {
if (!hasfocus) {
event.preventDefault();
$('#buttonID').trigger('click');
//hasfocus = true;
}
else {
//event.preventDefault();
//$('#buttonID').trigger('click');
}
}
})

Why is tab keypress causing focus change also triggering keyup event?

Pressing the tab key which triggers a focus change is also received by the input receiving the focus as a keyup.
a: <input type='text'/><br/>
b: <input type='text' onkeyup='alert("wtf?")'/><br/>
http://jsfiddle.net/59SnP/
As my control also uses tab (not in the example), I would want the focus related keyup event being consumed (but I want to receive other non-focus-change related tab events). I tried to research the rationale behind the current behavior but found nothing. The question: Where is this current behavior specified (event not consumed by focus change), and what would be a cross-browser workaround to force consuming it. Thx.
You can try this. I changed your keyup event in your input :
<input type='text' onkeyup="if(!tabPressed){ alert('This is it !'); }"/>
And I added a little event handler which will raise a flag when the tab button is pressed :
var tabPressed = false;
document.addEventListener('keydown', function (e) {
if(e.keyCode == 9) {
tabPressed = true;
} else {
tabPressed = false;
}
}, false);
Based on Nathan's insight, here is a fully working example:
// First part of Nathan's HACK (set a sentinel when a focus changing tab has happened)
var tabPressed = false;
// remove this listener to break the functionality
$(document).on("keydown", function (e) {
if(e.keyCode == 9) {
tabPressed = true;
} else {
tabPressed = false;
}
});
// The listener on the client input that would kill the keyup tab event upon focus change
$("#magic").on("keyup", function(e) {
if (tabPressed && e.keyCode==9) {
tabPressed = false; // reset the sentinel
e.stopImmediatePropagation()
e.preventDefault()
}
})
And here is the second part, which is a simple skeleton of something meaningful. We disable TAB inside the input, and log it as we do with other keyups:
$("#magic").on("keydown", function(e) {
if (e.keyCode==9) {
e.preventDefault()
e.stopPropagation()
}
})
$("#magic").on("keyup", function(e) {
$(this).val($(this).val() + " " + e.keyCode)
e.stopPropagation()
e.preventDefault()
})
The HTML backing the story is as simple as:
a: <input type='text'/><br/>
b: <input type='text'/><br/>
c: <input type='text' id='magic'/><br/>
If you want to play with it, here it is on jsfiddle
NOTE: This still is not the perfect solution, the sentinel is just reset inside the control, so if a tabpress moving the focus does not activate our input, the sentinel stucks, and the first event will be swallowed.. So here is an example of wrong behaviour:
Click on input A
Press TAB (focus moves to input B, tabPressed becomes true)
Click on input C
Press TAB (it is eaten up as sentinel is true)
Press TAB (now it goes through)
Still it is slightly better to have to press TAB twice as to have something happening automatically, wo user control...

modal close button

I have a div which is in a class="modal", and I written a function in jQuery that closes this div when i press "esc" :
$(document).keypress(function (e) {
if (e.keyCode == 27) {
if ($('.modal:visible > .icon32').length) $('.modal:visible > .icon32')[0].click();
}
});
everything works perfect in firefox, but in chrome does not, what could cause this problem?
I have observed keypress have issues with IE as well. use keydown event instead.The keydown event happens when the key is pushed down. Immediately after that keypress event occurs. When you release key keyup event happens.
$(document).keydown(function (e) {
if (e.keyCode == 27) {
if ($('.modal:visible > .icon32').length) $('.modal:visible > .icon32')[0].click();
}
});

Categories

Resources