Prevent right/left arrow navigation in select - javascript

I have 3 selects that I am enabling keyboard navigation(right and left arrow keys) to move between them. The default behavior when pressing the right or left arrow key is to move up/down the list.
My solution works moving between the selects, but every time you move to a new select, the selected value in the select that you just moved from gets moved up or down depending on which arrow you pressed.
Is there a way to prevent the default right and left arrow keys for the selects? I have tried e.preventPropagation and e.preventDefault but that doesn't seem to work.
JSFIDDLE

I just figured it out. I was binding to keypress event, when I needed to bind to the keydown event. When binding to keydown then you can use e.preventDefault().
JSFIDDLE SOLUTION

Since OP's solution does not work in Firefox, I created a workaround for the known bug in Firefox.
Basically event.preventDefault doesn't prevent ← and → on <select> nodes in Firefox.
So here's the workaround in action.
For more information on this, see my detailed answer on similar question

No way to get it work in Firefox preventing event default.... And Ruud solution is too complicated. So I've implemented that simple and clean solution, based on the same idea:
$('select').on('keydown', function( e ){
switch(e.keyCode) {
// User pressed "left" or "right" arrow
case 37:
case 39:
var val = $(this).val();
var $slt = $(this).one('change', function(){
$slt.val( val ).change();
});
break;
}
});
The only inconvenient is that "change" event is triggered twice, so you're app may take care about that.

Related

Holding down arrows key constantly triggers keyUP event

Here's all I'm doing:
$(document).keydown(function(e) {
e.preventDefault();
console.debug(e.keyCode, "down");
});
$(document).keyup(function(e) {
e.preventDefault();
console.debug(e.keyCode, "up");
});
You can see the problem here: http://jsfiddle.net/pJgyu/32530/
If I hold down a letter key, keydown is fired constantly until I let go. Then keyup fires once. That seems like the correct behavior.
If I hold down an arrow key, keydown and keyup alternate constantly. Why is keyup firing?
I've tried it without the "e.preventDefault();".
Also, after holding an arrow key, SOMETIMES letter keys display the same strange behavior.
Your keyboard may be broken. I don't have that issue when I try to replicate it in your jsfiddle.
It is not only the keyboard that has to be broken.
I had the same issue and spent some time googling and debugging it, and only after a couple of painful hours I remembered about my key mapping software that I use. My AutoHotkey scripts do several things with special keys, such as arrows, and this was the reason for the issue.

How to display only one key if i hold the key down in the textarea

Is There any possible way to display only one character when a key is pressed DOWN for a longer period of time what I mean is when I press lets say 's' DOWN for a longer period of time I want only 's' displayed and I don't want this to happen 'ssssssssssssssssssssssssssssssssssssssss....' .
And whit out using this method because this brings on the problem that if a user types fast and presses two keys at the same time only the second one will get displayed for example if I press down 'k' and press down whit out letting 'k' go the 'p' only the 'p' will get displayed.
var textarea='';
document.getElementById('textareaID').onkeydown=keydown;
document.getElementById('textareaID').onkeyup=keyup;
function keydown () {
this.value=textarea;
}
function keyup () {
textarea=this.value;
this.value=textarea;
}
And please do not say using counters because it doesn't work for some reason believe me I have tried for the last 3 days.
http://toki-woki.net/lab/long-press/ this is what i am basically trying to do but I cant understand how the part where you hold the key down and only one is displayed out is done and of course if i press a key and while the key is down i press another one both of them get displayed rest is easy.
So i would love and explanation its driving me crazy.
Alright I think I got it.
1: On keydown cancel the input to the textarea.
2: On keyup put in the clicked letter.
document.getElementById('textareaID').onkeydown=keydown;
document.getElementById('textareaID').onkeyup=keyup;
// keydown is run more than once if held down hence "ssssssss"
function keydown (event) {
// cancel input
}
// since the keyup event is only fired once we will do most of the work here
function keyup (event) {
// insert input
}
Here is the code (there are comments so you can see what's going on):
http://jsfiddle.net/NerfAnarchist/gXVuC/
As commenter PA pointed out, I think this is bad practice to alter native behavior of textbox or textareas. See your other options before doing this.
...But IF you have to do it:
You can use the keyDown event to let the event pass on condition that it is followed by a keyUp event. The following code is based on this fiddle.
​document.getElementById('box').addEventListener('keydown', function(event){
// Superglobal window.characterPrinted to detect if the event has already fired.
if(window.characterPrinted != true){
window.characterPrinted = true;
this.value += String.fromCharCode(event.keyCode);
event.preventDefault();
}
})​​​​​​​​;
document.getElementById('box').addEventListener('keyup', function(event){
// Reset superglobal
window.characterPrinted = false;
});
Note that this code uses addEventListener and preventDefault, which is not guaranteed to work in older browsers. You'll need to bind events using different methods. (I'm looking at you, IE7).
Another note: this code adds to the textarea. Therefore, if a delete key pressed, it will try to add a delete, which does nothing. You can do an event.keyCode filtering to see if it's a letter before fiddling with the event itself, much like Michael suggested.

Detect when mouse actually moves, not just when the page moves

I'm having a pretty big problem trying to create navigation on my page. If the mouse enters an element then it selects it, then if you use arrow keys it will select the elements relative to the selected one. However this is an issue when the arrow keys cause the page to scroll, because (depending on the position of the mouse) it will select the appropriate element then instantly select the item the mouse is now over after the page moved (even if you didn't move the mouse).
Does anyone know how to fix this problem? I tried tinkering with it but none of my solutions seemed to work. Any help is appreciated, thank you.
It sounds like you should bind the "select when mouse enters" event on mousemove and unbind said event on mousestop. mousestop does not exist on its own, so you will have to create it somehow or use a plugin (there are at least a few out there such as https://github.com/richardscarrott/jquery-mousestop-event/ ). I think this would be the simplest solution, but your UI seems a little bizarre (you want the arrow key to scroll the page normally and "select" an element that's possibly larger than the scroll size?)
Not sure I completely understand, but you should be able to use a combination of the mousemove and keypress events:
$("#element").mousemove(function(e){
alert("mouse moved");
});
$("#element").keypress(function(e){
if (e.keyCode == 38 || e.keyCode == 40){ //up & down arrow keys
e.preventDefault();
}
});
Try returning false from the keyboard event handler where you check for arrow keys:
element.onkeypress = function(ev) {
// ...
return false;
}
This will prevent the "default behavior" that the browser has for the event, which is to scroll. This works also for links, for example: if you return false from a click event handler for a link, clicking the link will not automatically follow it.

Can't use jquery's click event handler to detect right click

In trying to detect a right mouse click with jquery, I noticed that the click event handler doesn't seem to be fired off with a right mouse click, while the mousedown or mouseup event handler's do.
For example, after a right click on the test div, the following alerts 'testing!':
$('#test').mousedown(function(e) {
alert('testing');
});
However, the following does not:
$('#test').click(function(e) {
alert('testing!');
});
Does anyone know why?
When you mousedown, the even fired has event.which
Taken from here: How to distinguish between left and right mouse click with jQuery
$('#element').mousedown(function(event) {
switch (event.which) {
case 1:
alert('Left mouse button pressed');
break;
case 2:
alert('Middle mouse button pressed');
break;
case 3:
alert('Right mouse button pressed');
break;
default:
alert('You have a strange mouse');
}
});
So instead of using .click(), use mousedown and check for the cases.
As this article puts it:
There are no click events for right button clicks in any browser.
So you're left with mousedown and mouseup in most browsers.
Not sure which browser(s) you've tested with, but according to MSDN the onclick fires "when the user clicks the left mouse button". I.e., by definition it doesn't occur for right (or middle) clicks. Given that's on MSDN you can expect IE to behave that way regardless of what the other browsers do.
(Onclick also fires for certain non-mouse things, like changing certain form elements with the keyboard, etc.)
I know jQuery tries to normalise behaviour between browsers, but if the browser doesn't fire the event at all...
There is at least one jQuery plugin that I know of that implements right-click: http://abeautifulsite.net/blog/2008/05/jquery-right-click-plugin/ (I haven't used it, but it looks good except that it notes that Opera doesn't support it).
I have also tried the following code to catch right mouse click for certain class of elements
$(".brick").mousedown(function (event) {
if (event.which === 3) {
currentRightClickedTileID = $(this).attr("id");
}
});
This code doesn't always catch the right click.

jQuery keyboard events

Using jQuery, I would like to capture a keyboard event that is:
before the user lifts their finger from the key
after the characters from the keyboard event have registered in the input box.
To clarify, view this example. When keypress fires, the input value has not been updated yet.
[Edit]
Apparently I wasn't clear as to what I need.
The function must be called before the user lifts their finger up from the key, but after the key's character is placed in the input box. So the following do not work:
keydown: at the keypress event, the value in the text box has not been updated
keypress: at the keypress event, the value in the text box has not been updated
keyup: this is called when the user lifts their finger, which is too late.
You can use the input event, which works in recent versions of all major browsers:
var input = document.getElementById("your_input_id");
input.oninput = function() {
alert(input.value);
};
Unfortunately, it doesn't work in IE <= 8. However, in those browsers you can use the propertychange event on the value property instead:
input.onpropertychange = function() {
if (window.event.propertyName == "value") {
alert(input.value);
}
};
SO regular JavaScript answerer #Andy E has covered this in detail on his blog: https://web.archive.org/web/20140626060232/http://whattheheadsaid.com/2011/10/update-html5-oninput-event-plugin-for-jquery
Use keyup event, an example on jsFiddle
$("textarea").keyup(function(e){
alert($(this).val());
});
It happens after you lift the key. I don't know what you want to achieve, but you can store the state before lifting the key (on keydown or keypress) and restoring later if needed. You also can stop the output in the keyup event using e.preventDefault(), so even after the key is up it will not register the values in the area.
You could listen on keydown event and store the value in a variable. That variable would have the value as it was before the new input, and the new input would be included in the keyup event
UPDATE:
Ok, I misunderstood your requirements, but there isn't an event that would meet your needs. The only thing I can think of to simulate this behaviour is the following:
listen on keydown/keypress
get the value from the event object (get event.which, then convert it to actual value)
use a variable like I mentioned in the original advice and concatenate the new input to it
Here is a fiddle: http://jsfiddle.net/HpXuU/13/
This is obviously not a perfect solution, as it needs some (one might argue unnecessary) work to get done right. I would advise to rethink your needs, but if this behavior is absolutely what you need, I think this is a step in the right direction.
You can use setTimeout:
$('input').keypress(function() {
var that = this;
setTimeout(function() {
// read that.value
}, 0);
});
Live demo: http://jsfiddle.net/HpXuU/8/

Categories