I am using X3DOM for a simple game, but I can't use keyboard keys the way I want to, because X3DOM reacts to them.
Example:
window.addEventListener('keydown', event => this.onKeyDown(event));
I want to have my own key event for if keyCode == 68. That works, but X3DOM reacts to it too, by changing the navigation mode and displaying an overlay.
How can I disable this?
disclaimer: I've never used x3dom, I was just poking around in the source code
there appears to be some code which disables keypress handling
this.disableKeys = x3dElem.getAttribute("keysEnabled");
this.disableKeys = this.disableKeys ? (this.disableKeys.toLowerCase() == "true") : false;
which is later read when setting up the keypress event handler:
this.onKeyPress = function (evt) {
if (!this.parent.disableKeys) {
evt.preventDefault();
this.parent.doc.onKeyPress(evt.charCode);
}
this.parent.doc.needRender = true;
}
So it appears setting keysEnabled=... attribute can turn this off. The oddity appears to be that their logic is backwards (?) for the condition:
x3dElem.getAttribute("keysEnabled") must be truthy (that is, it must have an attribute)
if that is falsey, this.disableKeys is always false
otherwise it is equal to that attribute's value lower-cased being equal to 'true'
So to disable keypress events, use <... keysEnabled="true" ...>
I made a github issue about the backwards logic, perhaps in the future it will be keysDisabled="true" instead
update:
in the latest version the attribute has been renamed to disableKeys so use <... disableKeys="true" ...>
You can use event.preventDefault to prevent X3DOM from reacting to that key:
window.addEventListener('keydown', event => {
if ((event.which === 68) || (event.keyCode === 68)){
event.preventDefault();
//
// ...
//
}
});
Related
I am new to javascript, and am writing a simple bookmarklet for a webpage that has a text input section. Basically what I need is a way to execute the following-
if ( ! (text_section).onkeydown ) {
do whatever
}
I need to ignore key-events when the user is typing inside an input field but otherwise trigger key-events for the entire page whenever the user presses a key. I do know that onkeydown is an event listener/handler I'm just trying to explain what I need to do more accurately.
Use an id for your text-section, for example "myTextSection". Apply the addEventListener to the whole document. If the target is anything else, than the textfield, do whatever:
document.addEventListener("keydown", (event) => {
if(event.target !== document.getElementById("myTextSection")){
//do whatever;
}
});
Note that this behaviour might be irritating for users, that navigate by keyboard (for example tab and space keys) through your page. So you might want to add another if statement checking whether the event.keyCode is alphanumeric. In this case the keyCode is in the ranges
[47-58] (for 0-9),
[64-91] (for A-Z) or
[96-123](for a-z)
You should add an event listener to the target element:
targetElement.addEventListener('keydown', (e) => {
// do something
});
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
It is also possible to use onkeydown property:
targetElement.onkeydown = (e) => {
// do something
}
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onkeydown
For reasons I have to rely on keypress instead of keydown/keyup. keypress repeatedly fires events if the key is pressed. How to track only the first press on a key?
For keydown/keyup this would not be a problem, since there is a dedicated keyup event. But this is not the case for keypress.
Check the 'repeat' property of the event (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
If it's false then it's the first event, true otherwise.
Example using jquery:
$("#someid").on("keypress", function(e){
if(!e.originalEvent.repeat){console.log("first keypress")};
})
It's true that the "repeat" attribute doesn't work in Safari. It's only available in Gecko-based browsers. In lieu of that, try this (if you absolutely MUST use "keypress" instead of the alternatives):
var lastCode = -1;
$("#someid").on("keypress", function(e) {
var code = e.keyCode || e.which;
if (lastCode !== code) {
// do something
}
lastCode = code;
});
I have a game captured inside of an Iframe within my body. Problem is, the entire page scrolls when the arrow keys are pressed. How can I prevent this? I don't want to disable scrolling with the arrow keys alogether, only when the game is being played.
Use a variable as a flag and add an event listener to see if that flag is present, if so, disable the key: Live demo here (click).
var flag = true;
document.body.addEventListener('keydown', function(e) {
var badKey = 40; //down array keyCode
if (flag && e.keyCode === badKey) {
e.preventDefault();
}
});
You can apply a key listener and stop the normal functioning of specific inputs based on conditions (like while playing a game)
I am programming a jQuery plugin which tracks specific events. I have provided 2 JSFiddle examples for the sanitised code to assist at the end of the question.
I am struggling to fathom why 2 particular events are not firing. The first function tracks when the user triggers the backspace or delete keys within an input or textarea field. The code for this:
// Keydown events
$this.keydown(function (e) {
var keyCode = e.keyCode || e.which;
// Tab key
if (e.keyCode === 9) {
alert('tab key');
} else if (e.keyCode === 8 || e.keyCode === 46) { // Backspace and Delete keys
if ($this.val() !== '') {
alert('Backspace or delete key');
}
}
});
I only wish to track the error-correction keys when a field is not empty. The tab key in the above example works as expected within the conditional statement. The backspace and delete keys do not work when inside the plugin and targeting the element in focus.
The second event not firing is tracking whether a user becomes idle. It is making use of jQuery idle timer plugin to manipulate the element in focus.
// Idle event
$this.focus(function() {
$this.idleTimer(3000).bind('idle.idleTimer', function() {
alert('Gone idle');
});
}).focusout(function() {
$this.idleTimer('destroy');
});
With both of these events I have refactored the code. They were outside of the plugin and targeted $('input, select, textarea') and worked as expected. I have brought them inside the plugin, and set them to $(this) to manipulate elements currently in focus. For most of the functions, this has worked without fault, but these 2 are proving problematic.
The first JSFiddle is with the 2 functions inside the plugin. tab works, whereas the correction keys do not. Strangely, in this example the idle function is firing (it does not in my dev environment). As this is working in the JSFiddle, I accept this may be difficult to resolve. Perhaps suggestions on handling an external plugin within my own to remedy this?
Fiddle 1
The second JSFiddle has taken the backspace and delete key functionality outside of the plugin and targets $('input, select, textarea') and now works.
Fiddle 2
For Fiddle1:
if ($this.val() !== '') {
alert('Backspace or delete key');
}
Look at what $this actually is.
I am displaying a form inside a div tag as a dialog to enter details.
In this form, I want to handle the ESC key using jQuery.
If any input tags have focus, keydown event will trigger. If the focus is on the form but not on any input tags then it will not trigger keydown event.
Here is my code:
$("#NewTicket").keydown(function(e) {
var unicode = e.keyCode ? e.keyCode : e.charCode
if (unicode == 27)
{
if (confirm("Are you sure you want to cancel?"))
return true
else
return false
}
});
Just add an id,class to the form
<form id="form">
....
and now do this :
$("#NewTicket,#form").keydown(function(e)
{
var unicode=e.keyCode? e.keyCode : e.charCode
if(unicode == 27)
{
if (confirm("Are you sure you want to cancel?"))
return true
else
return false
}
)};
This should work
You can't focus on forms. If you wan't to handle keydown on elements that don't get focus (such as divs or forms) you have to bind it to the document.
Turns out that jQuery automatically adds :focus selector which enables you to find the focused element by using $(':focus')
I believe that if you put your form in an element made focusable using tabIndex, like , or this focusable div is the container element inside the form, then you can bind the keyDown to this div instead. It works cross browser as far as I've tested but I've not seen this solution discussed much, so curious as to anyone's comments about this.
I know this is an old question but someone still might be looking for an answer.
Usually, I do capture key down at global level then forward it to a function and handle it there. For your needs, you can get nodeName. (Tested in FF, Chrome)
$(document).keydown((e)=>{//Capture Key
if(["INPUT","TEXTAREA"].indexOf(e.target.nodeName)!==-1){//If input in focus
console.log("INPUT FOCUSED",e.code,e.keyCode);
if(e.keyCode==27 || e.code=="Escape"){//Capture Escape key
console.log('ESC');
}
}
});