Consider the following HTML5+Javascript:
$(function() {
$('#edit').hide();
$('#value')
.css('cursor', 'pointer')
.click(function() {
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
});
$('#edit input')
.keyup(function(e) {
if (e.keyCode == 13) { // <enter>
$('#value').show();
$('#edit').hide();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="value">
<a href="#">hello</a>
</div>
<div id="edit">
<input type="text" value="hello" />
</div>
Originally, all this did was to capture click events on the text hello
, replacing the text with an input box. When the user then hit Enter, the new text would be saved to server via AJAX and the input box again replaced with just the text.
Now I've added the a
tag to allow navigation via Tab+Enter rather than only using the mouse (accessibility; yay!), but I'm finding that, when doing so, the call to focus()
magically triggers the keyup()
event. (I know this because commenting out the call to focus()
otherwise results in the desired behaviour.)
The result is that tabbing and entering onto the text opens but then immediately closes the input
box, and as far as the user's concerned, nothing has happened at all.
Why is the input
's keyup
handler being triggered by a click
event on a completely unrelated element? How can I stop this from happening?
hello
hello
disappears; textbox appears, with caret inside ithello
reappearshello
is in focushello
disappears; textbox appears, with caret inside ithello
reappears ... before I have a chance to do anything.Explanation. Use a variable to store the timeout function. Then use clearTimeout() to clear this variable of any active timeout functions, and then use setTimeout() to set the active timeout function again.
How to remove keyup event in jQuery? jQuery unbind() Method The unbind() method was deprecated in version 3.0. Use the off() method instead. The unbind() method removes event handlers from selected elements.
Use the keypress event instead. It's the only key event which will give you information about the character that was typed, via the which property in most browsers and (confusingly) the keyCode property in IE. Using that, you can conditionally suppress the keypress event based on the character typed.
The keyup event is fired when a key is released. The keydown and keyup events provide a code indicating which key is pressed, while keypress indicates which character was entered. For example, a lowercase "a" will be reported as 65 by keydown and keyup , but as 97 by keypress .
So the problem is that when you press the enter key, the keyup
event is fired when you release the key.
This creates a flow like the following: 1, click the link (press enter key) 2, link hides 3, focus is given to text input (enter key is still pressed at this point) 4, release of key (keyup event is fired)
If you change the event to keydown
then pressing enter on the link will not conflict the input because that input doesn't have focus.
Additionally, using the same code in the keydown event that you had in the keyup event will still do the exact same thing (ie press enter and the input hides and the link shows).
EDIT
https://jsfiddle.net/geyut7uv/
The only solid solution that I could find, was to create a "blocker" variable that "disables" the keydown event. I've attached it to the link only when the keydown is clicked. This is checked on the keydown event by the input which will be immediately triggered if a user holds the key down.
It's only when the enter key keyup event is triggered that I allow the "blocker" variable pass.
Ideally, I'd like to remove all global scope variables, but I couldn't find a way to recognize that an event (keydown) was currently in use.
<div id="value">
<a href="#">hello</a>
</div>
<div id="edit">
<input type="text" value="hello" />
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
var enter_enabled = true;
$('#edit').hide();
$('#value')
.css('cursor', 'pointer')
.click(function() {
$('#edit').show();
$('#edit input').focus();
$('#value').hide();
}).keydown(function(e){
enter_enabled = false;
});
$('#edit input')
.keydown(function(e){
if(e.keyCode == 13 && enter_enabled){
$('#value').show();
$('#edit').hide();
}
})
.keyup(function(e){
if(e.keyCode == 13){
enter_enabled = true;
}
});
});
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With