I have an html form.
It uses keyboard navigation (with arrow keys) to move between fields including the enter key.
It periodically needs to prompt the user for acceptance of information.
The enter key is picked up on both the button and in the form field.
Problem: When the user hits ENTER on the accept button it is triggering double events in my form. Shifting the focus 2 fields instead of 1.
I have code that demonstrates exactly what I'm talking about here:
Original Post http://jsfiddle.net/mcraig_brs/UgUUr/1/
Modified Post http://jsfiddle.net/mcraig_brs/UgUUr/2/
Here is the sample HTML:
<button id="myButton">Press Enter On Me</button><br>
<input type="text" id="text1" class="tInput" data-index="0"><br>
<input type="text" id="text2" class="tInput" data-index="1"><br>
<input type="text" id="text3" class="tInput" data-index="2"><br>
<div id="log"></div>
Here is the sample JS:
function log ( data ) {
$('#log').append(data + "<br>");
}
function focusOn(index) {
log("focusOn(index): " + index);
$('input.tInput').eq(index).focus();
}
function focusNext( currentIndex ) {
log("focusNext(currentIndex):" + currentIndex);
focusOn(currentIndex + 1);
}
function focusPrevious (currentIndex) {
log('focusPrevious(currentIndex):' + currentIndex);
focusOn(currentIndex - 1);
}
$('#myButton').on('click', function(e) {
log("event:click #myButton");
focusOn(0);
});
$('input.tInput').on('keyup', function(e) {
switch (e.which) {
case 13:
log("event:ENTER key in input.tInput");
focusNext($(this).data('index'));
break;
case 38:
log("event:UP ARROW key in input.tInput");
focusPrevious($(this).data('index'));
break;
case 40:
log('event:DOWN ARROW key in input.tInput');
focusNext($(this).data('index'));
break;
}
});
When I press "ENTER" while the focus is on the button in the current code I get the following output in the log div:
event:click #myButton
focusOn(index): 0
event:ENTER key in input.tInput
focusNext(currentIndex):0
focusOn(index): 1
(At the moment in jsFiddle the only way I can get to the button is to focus on the first text field and shift+tab back to it so it has focus, so that I can press ENTER on it. But in the live code it is automatically focused for the user.)
Question: How can I prevent this type of double event from triggering? I have tried e.stopPropagation() but that did not yield the results I was looking for. When the user pressed ENTER I want the focus to advance only one field.
I have been wrestling with this for a few days so any help would be greatly appreciated. Please note that if a user clicks on the button with the mouse it works properly, it is only the ENTER key that triggers the double event.
Note: I had to modify my question slightly to better convey the constraints.
keyup is triggering the issue, change it to keypress
$('input.tInput').on('keypress', function(e) {
switch (e.which) {
case 13:
log("event:ENTER key in input.tInput");
focusNext($(this).data('index'));
break;
}
});
from http://www.quirksmode.org/dom/events/keys.html
keypress
Fires when an actual character is being inserted in, for instance, a text input. It repeats while the user keeps the key depressed.
keyup
Fires when the user releases a key, after the default action of that key has been performed.
---- edit ---
To catch key press and keyup both, I would suggest to define it separately, http://jsfiddle.net/UgUUr/3/
$('input.tInput').on('keypress', function(e) {
switch (e.which) {
case 13:
log("event:ENTER key in input.tInput");
focusNext($(this).data('index'));
break;
}
});
$('input.tInput').on('keyup', function(e) {
switch (e.which) {
case 38:
log("event:UP ARROW key in input.tInput");
focusPrevious($(this).data('index'));
break;
case 40:
log('event:DOWN ARROW key in input.tInput');
focusNext($(this).data('index'));
break;
}
});
Use keypress event instead:
$('input.tInput').on('keypress', function(e) {
switch (e.which) {
case 13:
log("event:ENTER key in input.tInput");
focusNext($(this).data('index'));
break;
}
});
DEMO
Related
I have looked online for answers on how to connect a specific keyboard key to a div element and so far what I have been able to only see was how to do a general key(onkeydown) What I am looking for is being a able to press a specific key by using keyCodes to detect that key so that it can call up a DIV element by id and make it active
var inpt = document.getElementById("11w");
inpt.addEventListener("keyup", function(e){
e.preventDefault();
if (e.keyCode==49)
document.getELementById("11w").click();
}
});
First thing, there is a syntax error in your code.
var inpt = document.getElementById("11w");
inpt.addEventListener("keyup", function(e){
e.preventDefault();
if (e.keyCode==49)
document.getELementById("11w").click();
}//<--------- syntax error
});
As I understand your question, this may be one of the solutions:
<textarea id="11w" placeholder="Press 1 or write 1"></textarea>
<br/>
<button id="btn">My value will change</button>
<script>
var inpt = document.getElementById("11w");
inpt.addEventListener("keyup", function(e){
e.preventDefault();
console.log(e.keyCode);
if (e.keyCode==49){
document.getElementById("btn").click();
}
});
document.getElementById("btn").addEventListener("click", function(e){
document.getElementById("btn").innerHTML = "I am clicked";
console.log("btn clicked");
});
</script>
You can listen on keyup events of the document then do what you please with each key.
DEMO
// Assingin to the keyup event of the document
document.onkeyup = (e) => {
// Getting the div element by it's id #test
const div = document.querySelector('#test');
// e.which returns the ascii code of the key that has been pressed
switch (e.which) {
case 83:
// 83 is lower case 's' (show) so we set the div to be block
div.style.display = 'block';
break;
case 72:
// 72 is lower case h (hide) so we set the div to be none
div.style.display = 'none';
break;
}
};
div {
width: 150px;
height: 150px;
background: blue;
}
<div id="test"></div>
This is just an example showing you how to bind a key to a certain element, it is not by any means bind to it, it just depends on the logic, we can add more logic to control two or more element with press of one key.
the point is that the code you write for each key will fire where you're even when you're typing in an input, that can be avoided, however i'll leave it to you :)
Hi I am writing key events for remote for that screen, ups and downs working properly, the problem is when the cursor is inside the text field my key events is not working.
if anybody knows about key events plz help me.
Controller.js
var unFocusText = function(){
$("#search_all")[0].blur();
};
case PV.yoohu.appConstants.keyCodes.BACK:
case PV.yoohu.appConstants.keyCodes.ESC:
break;
case PV.yoohu.appConstants.keyCodes.SELECT:
if (_isSearchItemHighlighted == 8) {
$("#search_all")[0].focus();
}
break;
case PV.yoohu.appConstants.keyCodes.DOWN:
if (searchScreen) {
if (0 <= _isSearchItemHighlighted && _isSearchItemHighlighted <= $scope.searchFilters.length-1) {
isSearchItemHighlighted = 8;
}
}
break;
case PV.yoohu.appConstants.keyCodes.RIGHT:
if (_isSearchItemHighlighted == 8) {
_isSearchItemHighlighted = 9;
unFocusText();
}
break;
case PV.yoohu.appConstants.keyCodes.UP:
if (_isSearchItemHighlighted == 8) {
_isSearchItemHighlighted = 0;
unFocusText();
}
<div id="searchCategory">
<div id="searchFilter" ng-repeat="item in searchFilters">
<input id="searchFilternames" type="radio" ng-model="selectedFilter.name"
value="{{item.name}}"
ng-class="{'selected-search-asset-border': isSearchItemHighlighted($index)}"
ng-checked="isItemChecked(item, $index)"/><span
ng-bind="item.name"></span>
</div>
</div>
<input type="text" id="search_all" class="input" placeholder="enter text" ng-class="{'selected-search-asset-border': isSearchItemHighlighted(8)}"
/>
<input type="image" id="searchButton"class="searchImage" src="resources/search1.png"
ng-class="{'selected-search-asset-border': isSearchItemHighlighted(9)}" ng-click="availableSearchList()" />
index no of the search textfield is 8, if i press enter, when the Red Border in Search textfield the cursor will be focused, but after that my key events are not working.
Actually i wants to move controller to right and up from the text field.
What is the wrong in my code, Please help me.
The best solution is:
$("your_input").keyup(function (e) {
if (e.keyCode == 13) {
// Do something
}
});
Another (worse) way is:
In case that your cursor is in the input and your key events arent working you should check every key which is pressed when the cursor is in the input. To do this you should add the change() function at your input and in the function you can check the keys that are pressed when the cursor is in the input
$( "your_input" ).change(function() {
var key_pressed = your_input.text().slice(-1);
if (key_pressed = "e" )
//do that
});
I am not advanced with Javascript. i was hoping for someone to simply explain the process to edit the following code.
this.hideNextButton();
this.hidePreviousButton();
var that = this;
Event.observe(document, 'keydown', function keydownCallback(e) {
var choiceID = null;
switch (e.keyCode) {
case 74: // 'j' was pressed
choiceID = 1;
break;
case 75: // 'k' was pressed
choiceID = 2;
break;
}
if (choiceID) {
Event.stopObserving(document, 'keydown', keydownCallback);
that.setChoiceValue(choiceID, true);
that.clickNextButton();
}
});
If a user wants to replace the click of a mouse with clicking a letter on the Keyboard, eg. Click J for the next question or to select yes, click A. I think that is what this code is doing but I'd like to pull it apart a bit to add or remove letters to complete additional tasks, such as next question etc.
Any help or pointing in the right direction is a help!
In the code you provided pressing 'j' or 'k' answers the current question by setting the choice value and goes to the next page. To add other keyboard presses you would additional cases to the switch using the appropriate keycode. For example, if you wanted 'j' to just go to the next page and 'a' to answer 'Yes', it would be something like this (remove the if(choiceID) section):
Event.observe(document, 'keydown', function keydownCallback(e) {
switch (e.keyCode) {
case 65: // 'a' was pressed
that.setChoiceValue(1, true);
break;
case 74: // 'j' was pressed
Event.stopObserving(document, 'keydown', keydownCallback);
that.clickNextButton();
}
});
You need to track pointed pointed element and call click event of pointed element when the key j is pressed.
var pointedElement;
document.onmousemove = function(e) {
pointedElement = e.srcElement;
}
document.onkeydown = function(e) {
switch (e.keyCode) {
case 74: // 'j' was pressed
pointedElement.click()
break;
}
}
Edit: My answer was just about the idea to change a click element in the whole window with another key but in your case you it is different. I can not help you by just looking this snippet but you need to change switch case block with the same functionality of buttons. What exactly those buttons are doing? You need to call the same functionality of next and previous keys are handling.
The following script does what it should, that is, it reacts on the keys "arrow left" and "arrow right". However, due to a keycode clash, it reacts on a single quote as well. It makes it impossible to enter that character into an input field. Can anything be done about that?
<script type="text/javascript">
onload = function(){
document.onkeypress=function(e){
if(window.event) e=window.event;
var keycode=(e.keyCode)?e.keyCode:e.which;
switch(keycode){
case 37: window.location.href='set.jsp?index=5';
break;
case 39: window.location.href='set.jsp?index=7';
break;
}
}
}
</script>
When the user presses the single quote key, the e.keyCode property is zero, and the e.which property is 39. Executing String.fromCharCode(39) returns a single quote.
You want the keyCode if that property is in the event object:
var keycode = "keyCode" in e ? e.keyCode : e.which;
That way you get zero for the keyCode when that property exists in the event object, and when the which property also exists.
document.onkeydown = function(event) {
event = event || window.event;
var keyCode = "keyCode" in event ? event.keyCode : event.which;
switch (keyCode) {
case 37: console.log("37 was pressed", event); break;
case 39: console.log("39 was pressed", event); break;
}
};
Edit #1: Other commenters and answers are correct. I forgot you shouldn't be detecting control keys with keypress events. Changed to onkeydown.
Full HTML example that works cross browser:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Key Codes Test</title>
</head>
<body>
<script type="text/javascript">
document.onkeydown = function(event) {
event = event || window.event;
var keyCode = "keyCode" in event ? event.keyCode : event.which;
switch (keyCode) {
case 37: console.log("37 was pressed", event); break;
case 39: console.log("39 was pressed", event); break;
}
};
</script>
<input type="text" size="30">
</body>
</html>
keypress should not capture control keys like left/right arrow. if you use keydown event, single quote keycode is 222 definitely no conflict
As it is a text input, it seems you'd also have a problem when someone is trying to use the arrow keys to move the cursor within the input. Thus, stopping event propagation/bubbling should be used, and can solve the main issue you're asking about.
// assuming you've grabbed an input in var input_ele
input_ele.onkeypress = function (e) {
e = e || window.event;
if (e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
};
Using this will stop the keypress event from leaving the input element, thereby never reaching the document element to trigger the unwanted behavior. In other words, you don't break the expected behavior of a very standard control element.
Use keydown instread of keypress
jS:
document.onkeydown=function(event){
if(window.event) event=window.event;
var keycode=(event.keyCode)?event.keyCode:event.which;
switch(keycode){
case 37: alert("an arrow");
break;
case 39: alert("another arrow");
break;
}
}
Fiddle : http://jsfiddle.net/p9x1Lj4u/2/
when I hit "enter" to choose an item from the jquery-autocomplete results, the form submits. Why this happens....
i should get the data in the text field and on second enter the form should submit...
please suggest where to change in autocomplete.js
Thanks in advance
try this:
Find the keydown event on the li, in the autocomplete.js file and then place this line at the end of the keydown`s event handler (it may have some switch statement, you are interested about the 13[ enter key code]),:
return false;
ex:
.keydown(function(e) {
// track last key pressed
lastKeyPressCode = e.keyCode;
switch(e.keyCode) {
case 38: // up
e.preventDefault();
moveSelect(-1);
break;
case 40: // down
e.preventDefault();
moveSelect(1);
break;
case 9: // tab
case 13: // return
if( selectCurrent() ){
// make sure to blur off the current field
$input.get(0).blur();
e.preventDefault();
return false; // ADD THIS !
}
break;
default:
active = -1;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(function(){onChange();}, options.delay);
break;
}
})
this will stop the event to further propagate and submit the form.