Why doesn't preventDefault() stop focus change after a Tab-keypress? - javascript

I was fiddling with preventDefault() and must be doing something wrong.
$("#input").bind("keypress", function(event) {
if(event.which == 9) {
event.preventDefault();
alert("You pressed tab.");
}
});
The tab functionality isn't prevented. What's wrong with this?

Try this FIDDLE. The input loses focus when you tab. Binding to the body fixes this.
$("body").on("keydown", function(event) {
if(event.which == 9) {
event.preventDefault();
alert("You pressed tab.");
}
});

The keypress event is simply not fired when the Tab is pressed - this also explains why there is no alert, independent of what preventing the default may do.
Changing the code to use keydown allows the Tab to be caught and prevents the default focus-change (in Chrome1, anyway).
$("#input").bind("keydown", function(event) {
if(event.which == 9) {
event.preventDefault();
}
});
1 I tested the above in Chrome 35 with jQuery 1.6-2.1; it does not work under the KO 3.0 library.

From the documentation on JQuery,
Note: as the keypress event isn't covered by any official specification, the actual behavior encountered when using it may differ across browsers, browser versions, and platforms.
This method is a shortcut for .on( "keypress", handler ) in the first two variations, and .trigger( "keypress" ) in the third.
The keypress event is sent to an element when the browser registers keyboard input. This is similar to the keydown event, except that modifier and non-printing keys such as Shift, Esc, and delete trigger keydown events but not keypress events. Other differences between the two events may arise depending on platform and browser.
So in this case you are using the wrong event. Also it might have browser compatibility issues.

Related

Javascript cannot capture ESC keyup event in Vivaldi browser

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');
}
}

How to disable enter key in input field

I am trying to stop the enter key from triggering all actions from other scripts on input fields.
Here is the code I am using:
$(document).bind("keydown", function(e) {
var code = e.keyCode || e.which;
if (code == 13) {
// alert('enter pressed');
e.preventDefault();
return false;
}
});
An example of the code in action is here http://jsfiddle.net/8SJYn/ ,
It should be disabling enter but it is not.
Opinions?
You can do it by turning off the keydown and blur events for the input created by the tagit for this element alone.
Try this:
$('#myTags + ul .ui-autocomplete-input').off('keydown').off('blur');
http://jsfiddle.net/JzJRY/
Go into tag-it.js, and on line 245, find this part and remove it:
event.which === $.ui.keyCode.ENTER
JavaScript events have a "bubbling" phase, where they fire first on the inner-most DOM element, and then work their way up to the top-level document. If you try to stop the event at the document level, as in your example code, it is too late.
In some browsers (Firefox, for one) there is a "capturing" phase that occurs before the bubbling phase, and it works in the opposite direction: from top down. You cannot add a capturing phase event handler using jQuery. You must use the native addEventListener function and pass true as the third parameter. If you add the code below into your jsfiddle, it will prevent the Enter keydown event in some browsers.
document.addEventListener('keydown', function (e) {
if (e.keyCode === 13) {
// alert('Enter keydown');
e.stopPropagation();
}
}, true);
Be aware that the tag-it control in your jsfiddle also performs its text-to-tag conversions on blur, so if you uncomment the alert statement above, it will perform its text-to-tag conversion anyway, because of the blur event that occurs when the alert message is displayed.
Lastly, if you want to prevent not just other scripts from processing the Enter keydown, but also the browser itself, add an e.preventDefault(); line to the above.

Keyup event listener fires when enter is pressed on Chrome's Ominbox

In chrome browser, when using this snippet:
$(document).on('keyup', function(){
alert("Hey");
});
Every time I press enter in the url bar (for example when I cut and paste the url of the page itself) the event listener fires.
Why does it happen?
EDIT:
It surprised me because url bar is not in document (maybe in window?) and firefox does not have this behaviour. When I look for e.target, Chrome Inspector shows body.
I thought this could be caused by event bubbling so I tried this:
$(document).on('keyup', function(e){
e.stopPropagation();
alert("Hey");
});
But it doesn't work.
How can I prevent it from being triggered?
This happens because once you hit enter in the omnibox, the focus turns to the page. If you tried the same thing with onkeydown, the omnibox would change nothing, because as you said, it isn't a part of the document. One way to filter the omnibox's false event out would be to check that every keyup has a pair keydown.
<script>
var down = false;
document.addEventListener('keydown', function (){
down = true;
}, false);
document.addEventListener('keyup', function (){
if(down === true){
alert('It was from the page!');
}
else{
alert('Omnibox. Ignore it.');
}
down = false;
}, false);
</script>
Demo.
Make your own HTML page and try it preferably, because PasteHTML.com stuffs it into an iframe. For it to work correctly there, click on the text first to give the iframe focus.
Demo.
Remember to use your mouse to focus on the omnibox and type, not a keyboard shortcut. (That fires the onkeydown event, creating a false positive)
Update: As of Chrome 35, this doesn't happen anymore. I don't know which version they fixed it on, however.
The solution for Chrome is simple: use keypress instead of keyup. This doesn't work in all cases (IE), so you may have to add a conditional to switch the type depending on the browser. However, this will solve your issue.
Note that looking for a specific keycode may negate your issue. Good luck.
You could filter for the keycode ...if that helps...13 is enter key
$(document).on('keyup', function(event){
if( parseInt(event.keyCode,10) !== 13 ){
alert("Hey");
}
});​
A possible solution is to slightly delay the "keyup" event handler registration. This will skip the first "spurious" trigger that seems to happen in Chrome and Safari.
$(function() {
setTimeout(
function() {
console.log("Delayed event attachment");
$(document).bind('keyup', log);
}, 10);
});
function log(e) {
console.log(e.target.localName);
}

Javascript/JQuery: how to add keypress/blur event that doesn't trigger twice with alert box? IE only

I have an input field that I would like to validate on when the user either presses enter or clicks away from it, for this I use the events keypress and blur. If the input fails validation, an alert box is called.
I noticed that in IE (all versions), if I press enter with invalid input, for some reason both the keypress and blur events are fired (I suspect it's the alert box, but it doesn't do this on FF/Chrome) and it shows two of the same alert box. How can I have it so only one is shown?
EDIT: In FF/Chrome, I now noticed that a second alert box appears when I click anywhere after I try to validate with enter.
Simplified code:
$("#input-field").keypress(function(event) {
if (event.keycode == 13) {
event.stopPropagation();
validate();
return false;
}
});
$("#input-field").blur(function() {
validate();
});
function validate() {
if ($("#input-field").val() == '') {
alert("Invalid input");
}
}
EDIT: Ah-ha. Not really a fix but a separate detail I forgot - I need to restore the invalid input to its previously valid value, so when the validate function checks the value again it doesn't fail twice.
I ended up just checking for an IE UserAgent and skipping the keypress event for IE (binding keypress and blur to the same function, as below). Not a direct or terrific solution, tragically, but I've been looking to solve the same problem to no avail. Some minor notes that might be helpful: jQuery normalizes which, so you can confidently use e.which == 13 with keypress. I'd also combine the functions into one bind, e.g.
$("#input-field").bind('blur keypress', function(e) {
if(e.which == 13) {
// keypress code (e.g. check for IE and return if so)
}
validate();
});
I've tried setting globals and using jQuery's data() to assign arbitrary flags to indicate whether (in your case) validation has already been triggered for the element, but the events trigger simultaneously or at least, if sequentially, rapidly enough that even with an opening line setting some flag to true did not do the trick. I'd read that putting in a tiny callback delay might help, but that is hella dirty and I wouldn't do it even as a workaround so I've not tested it. stopPropagation() and preventDefault() also did not help.
Firefox does not get the keypress event right. Those events are only triggered when a key combination that produces a character is pressed (which is not the same as pressing any key).
Use keydown instead (as this is probably the only event IE handles correctly - as it should, since MS "invented" it ;-) ).
See http://www.quirksmode.org/dom/events/keys.html.

Remap Enter keydown to trigger Shift+Enter in JavaScript

I'm using Mootools, but a generic answer is fine.
I would like to remap the 'Enter' key in a web application.
When they hit 'Enter' it should react as though the 'Shift-Enter' has been pressed.
I would just stop the enter event, and use exec.insertHTML or its ilk, but FF's implementation is buggy on many elements.
I imagine that I could fire a key event, same as I could fire a click or other event:
click: $('myElement').fireEvent('click', arg1);
keyevent: $('myElement').fireEvent('keydown' ???);
But I can't figure out how.
I don't know exactly what you're looking for, but the following fires the 'shiftenter' event when the enter-key is pressed. Notice that you have to specify the 'shiftenter' event yourself.
$('element').addEvent('keydown', function(e) {
new Event(e).stop();
if (e.key == 'enter') {
this.fireEvent('shiftenter');
}
});

Categories