so the thing is that 'keydown' event calls after the keyup event if multiple keys are pressed and released in particular order in chrome, but seems like there is no such issue in firefox browser
for example we have these events on window with if (e.repeat) return to prevent repeat
window.addEventListener('keydown', (e) => {
if (e.repeat) return
console.log(e.key, 'pressed')
})
window.addEventListener('keyup', (e) => {
console.log(e.key, 'released')
})
and here is the result of me pressing multiple keys at once and then releasing them one by one
firefox
chrome
any ideas of how to fix this? i think it has something to do with if (e.repeat) return and there is a better way to prevent this event repeat on button hold
I tried doing it on Chrome and Firefox, and it worked as predicted in both of them.
Could you please say what environment you are using this piece of code on?
Related
I am developing a Javascript library (AnyList) in which users may press the ESC key to abort editing an input field. This is implemented by catching the ESC keyup event (using jQuery):
inp_elem.on("keyup", init_opt, $.proxy(this._processKeyup,this));
...
$.any.DataView.prototype._processKeyup = function (event)
{
if (event.preventDefault)
event.preventDefault();
if (event.type == "keyup" && event.which == 27) { // ESC. In Vivaldi, we never get here.
...
}
...
This works fine in Firefox, Edge, Chrome, etc. but not in the Vivaldi browser - the _processKeyup method is never called.
Vivaldi uses the ESC key to stop the loading of a html page but so do other browsers, and even if I delete the ESC keyboard mapping (there is an option for this in Vivaldi), I am not able to catch the ESC event in my Javascript.
Can anybody help? I really like the Vivaldi browser and would like to see it succeed, but this behaviour breaks my script unneccessarily and is quite annoying.
It seems that Vivaldi browser is catching the keyUp event, so you'd better to use keyDown event instead.
A working solution could be something like that:
elem.onkeydown = function (event) {
if (event.type === "keydown" && event.key === 'Escape') {
alert('esc - everywhere');
}
}
jsfiddle
<div class='wrapper'>
<button class='child'>Click me</button>
</div>
function h(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
alert(e.type);
return false;
}
document.querySelector('.wrapper').addEventListener('mouseup', h, false);
document.querySelector('.child').addEventListener('click', h, false);
I expect this to prevent the 'click' event from firing, but it doesn't. However, changing mouseup to mousedown does in fact prevent the click event.
I've also tried setting the useCapture argument to true, and that also doesn't produce the desired behavior with mouseup. I've tested this on Chrome and Firefox. Before I file bugs, I figured I'd ask here.
Is this a bug in current browsers, or is it documented behavior?
I've reviewed the W3C standard (DOM level 2), and I wasn't able to find anything that could explain this behavior, but I could have missed something.
In my particular case, I'm trying to decouple two pieces of code that listen to events on the same element, and I figured using capture events on the part that has priority would be the most elegant way to solve this, but then I ran into this problem. FWIW, I only have to support officially supported versions of FF and Chrome (includes ESR for FF).
Check out this quirksmode article
The click event:
Fires when a mousedown and mouseup event occur on the same element.
So when the mouse click is released, both the mouseup and click events are fired, click doesn't wait for the mouseup callback to finish. Almost always, mouseup and click can be used synonymously.
In order to cancel the click, like you demonstrated, you can return false in the mousedown event callback which prevents the click event from ever completing.
I just want to provide my work around for this issue:
let click_works = true
this.addEventListener('mousedown', e => {
click_works = // condition why the click may work or not
})
this.addEventListener('click', e => {
if (click_works) // Do your stuff
})
Hopefully, it will help someone.
Finally found a way to prevent click event from firing. Tested on latest Chromium and Firefox. It may be some bug or implementation details.
Solution
Handle onpointerdown or onpointerup event, remove the element and insert it in the same position.
<span>
<button onpointerdown="let parent = this.parentElement; this.remove(); parent.appendChild(this);" onclick="alert();">TEST</button>
</span>
Result
onpointerdown
onmousedown
onpointerup
onmouseup
<-- no click event occures
I have some code to create hotkeys for a web application. All of the hotkeys work in IE and Firefox, however Ctrl+PgUp and Ctrl+PgDn are not working in Chrome.
After digging around for answers and writing some custom test code, I believe I have determined that this is because those events fire, in Chrome, on keyup instead of keydown.
The default Chrome handlers for those events are firing instead of mine (or at least first) and switching the browser to the next or previous tab. If I use the hotkey to switch back to the tab with my application then my handlers catch the event.
So my question is, is there any way to catch these events in Chrome and prevent the default functionality from running?
The code in question is:
//These work in IE and Firefox
$(this).bind('keydown', 'ctrl+pageup', (evt) => {
this.prevPage();
return false;
});
$(this).bind('keydown', 'ctrl+pagedown', (evt) => {
this.nextPage();
return false;
});
//These catch the event in chrome, but it's too late
$(this).bind('keyup', 'ctrl+pageup', (evt) => {
this.prevPage();
return false;
});
$(this).bind('keyup', 'ctrl+pagedown', (evt) => {
this.nextPage();
return false;
});
It does exactly what I want in IE and Firefox, but not Chrome. I have tried evt.preventDefault(), evt.stopImmediatePropagation and evt.stopPropagation. However, it does not work (I believe because my handlers are being called after the browser handlers).
Check a similar question on this link:
Chrome - Javascript prevent default Ctrl + MouseWheel behavior
They say its impossible on chrome and its still being addressed!
I'm using this to disable the 'scrolling' effect the spacebar has in a browser. Will this affect other keypress events too?
window.onkeydown = function(e) {
return !(e.keyCode == 32);
};
Could someone please explain what this is doing? I'm not sure if this code is bad, but it seems to disable other keypress related codes in my page, and I want to make sure this isn't the reason.
Thanks!
ASCII code 32 is the ASCII value that represents the spacebar key, and your code is essentially telling the browser to return false whenever that keycode is detected. Since false is returned, the scrollbar effect you speak of is in fact successfully disabled.
However, the unfortunate side effect of this convenient spacebar-scroll-disabling function is that it disables spacebar keypresses everywhere on the page.
Instead of returning false, if the keycode is detected, pass the current scrollTop value into a closure that returns a function to a setTimeout event. When the setTimeout fires, the scrollTop position is reset back to the value it was in when the setTimeout event was first registered.
window.onkeydown = function(e) {
if(event.keyCode == 32) { // alert($(document).scrollTop() );
setTimeout(
(function(scrollval) {
return function() {
$(document).scrollTop(scrollval);
};
})( $(document).scrollTop() ), 0);
}
};
Your users can still conveniently make use of spacebars in input textboxes and textareas, and at the same time, pressing the spacebar key while not focused on a text element will no longer result in the page scrolling.
Under the hood, the scroll is still taking place. It's just being reset at a rate fast enough to where the user doesn't notice.
If you increase this value to 100 or 1000, it will give you a better idea of what is going on under the hood. You'll actually see the page scroll and then get set back to the previous scroll position.
This was only tested in Chrome and Firefox 13! So you may have to adjust the setTimeout duration -- currently 0 -- to a different value in browsers like Internet Explorer. Be prepared to gracefully degrade -- by supporting this feature only in modern browsers -- if necessary.
UPDATE:
For reference, below is the method to use to make this compatible in the major browsers. It has been tested in Chrome, Firefox, IE8, IE9, and Safari.
While it does work in IE8/IE9, it isn't very smooth.
// put the eventhandler in a named function so it can be easily assigned
// to other events.
function noScrollEvent(e) {
e = e || window.event;
if(e.keyCode == 32) {
setTimeout(
(function(scrollval) {
return function() {
$(document).scrollTop(scrollval);
};
})( $(document).scrollTop() ), 0);
}
}
// Chrome and Firefox must use onkeydown
window.onkeydown = noScrollEvent;
// Internet Explorer 8 and 9 and Safari must use onkeypress
window.document.onkeypress = noScrollEvent;
If another element is bound to the keydown event it will not be effected by this code
See my fiddle and try adding and remove the textarea listening to the keydown event
window.onkeydown = function(e) {
return !(e.keyCode == 32);
};
document.getElementsByTagName("textarea")[0].onkeydown = function(e) {
alert("hi");
}
http://jsfiddle.net/HnD4Y/
The answer above with the setTimeout did not work for me at all on Chome with a delay of 0. With a delay bumped above 50ms, it began to work, but that caused a noticeable page jump. I believe that setTimeout was scrolling the page up too early, then Chrome moved it down later.
Below is my solution that is working well. It returns false on the keydown event to prevent the browser from doing a page-down. Then you make sure event you set up on your button etc. to use the keyup event instead.
$(mySelector).keyup(eventHandlerFunction);
[dom element].onkeydown = function(event) {
if (event.keyCode == 32) {return false;}
};
Note: input fields will not reflect spacebar key events if they or their parent are covered by this onkeydown handler
I'm using Prototype and doing Event.observe on window.document.
I'm catching enter (keyCode 13) and alt+f (altKey && keyCode=70).
My code is working super with firefox, IE and chrome. With Opera no. Enter is catched, but only if my focus is not in any text input. Alt+F is not working at all.
Is it bug in Prototype or I need to do something 'extra' on Opera in order to go on? As i said, in all other browser my code works....
Firstly, the following is a helpful resource: http://unixpapa.com/js/key.html
Secondly, you should know there is a difference between keydown (or keyup) and keypress. keypress does not typically allow modifier keys, though it does allow some in Opera like control. Better to use keydown for cross-browser consistency.
I get keyCode === 13 in Opera 11.10 no matter whether the textbox is entered or not, and no matter whether using Prototype like this:
Event.observe(document, 'keydown', function (e) {
alert(e.charCode+'::'+e.keyCode);
});
or using the native method directly (using attachEvent for IE):
if (document.addEventListener) {
document.addEventListener('keydown', function (e) {
alert(e.charCode+'::'+e.keyCode);
}, false);
}
else { // IE
document.attachEvent('onkeypress', function (e) {
alert(e.charCode+'::'+e.keyCode);
});
}
However, alt is indeed not detected inside a textbox unless combined with a control or function key (though that doesn't work in Chrome or IE). This may be because Windows uses alt to give access to the applications menu bar.
You could try using control key and using preventDefault() (to avoid default behaviors like ctrl-f doing a page find) though this might annoy your users who might not want their browser behaviors disabled for your page.
Alt-F activates the menu and Opera doesn't let JavaScript handle this key press.