admin管理员组文章数量:1406312
I am creating a web form with a grid of inputs for creating objects in Django.
It seems that when the focus is on a drop down menu, the up and left arrows select the previous item and right / down arrows select the next item.
I would like to use the left / right arrows to move focus left or right on the grid (a bit like excel does). Can I disable the left / right arrows from changing the menu choice, (while keeping the functionality for the up / down arrows)?
I am creating a web form with a grid of inputs for creating objects in Django.
It seems that when the focus is on a drop down menu, the up and left arrows select the previous item and right / down arrows select the next item.
I would like to use the left / right arrows to move focus left or right on the grid (a bit like excel does). Can I disable the left / right arrows from changing the menu choice, (while keeping the functionality for the up / down arrows)?
Share Improve this question asked Mar 11, 2014 at 9:33 wobbily_colwobbily_col 12k14 gold badges64 silver badges88 bronze badges 3- Thanks, but it doesn't seem to work in Firefox, only Chrome. – wobbily_col Commented Mar 11, 2014 at 10:31
- 1 I have updated the fiddle to work with firefox. I stumbled upon a issue with firefox not preventing the default behavior. Im not getting it perfect for FF :( – A1rPun Commented Mar 11, 2014 at 10:57
- It seems to be working in the version I am using. Thanks for the replies. – wobbily_col Commented Mar 11, 2014 at 12:07
4 Answers
Reset to default 3Changing default behavior of controls is sometimes frustrating for users. But other times the user expect it works like excel like in your case :)
You can do something like this:
var selects = document.getElementsByTagName('select');
for (var i = 0; i < selects.length; i++){
selects[i].addEventListener('keydown',function(e){
var key = e.which || e.keyCode;
if(key == 37){
var previousSibling = this.previousSibling;
while(previousSibling && previousSibling.nodeType != 1) {
previousSibling = previousSibling.previousSibling
}
previousSibling.focus();
e.preventDefault();
}else if(key === 39){
var nextSibling = this.nextSibling;
while(nextSibling && nextSibling.nodeType != 1) {
nextSibling = nextSibling.nextSibling
}
nextSibling.focus();
e.preventDefault();
}
})
}
Key 37 = ← and key 39 is →.
e.preventDefault();
prevents the default behaviour of the key you pressed.
Fiddle
While A1rPun's answer does what was asked, it does not work in Firefox. This is because of this Firefox bug, basically event.preventDefault
doesn't prevent ← and → on <select>
nodes.
Workaround
I made a workaround for this issue that can be used to improve A1rPun's answer to support Firefox.
function ensurePreventDefault(select) {
var selectedIndex, scrollTop;
function saveState() {
selectedIndex = select.selectedIndex;
scrollTop = select.scrollTop;
}
saveState();
if (!select.multiple && !select.size) {
select.addEventListener('change', saveState);
}
// use setTimeout to wait a frame and see if the selected index was changed
setTimeout(function () {
select.removeEventListener('change', saveState);
if (select.selectedIndex !== selectedIndex) {
// Damn you, Firefox!
select.selectedIndex = selectedIndex;
select.scrollTop = scrollTop;
}
});
}
Short version: store the selectedIndex
and restore it back a frame later.
Long version: store the selectedIndex
, so that we can check later if it was changed by Firefox, using setTimeout
. You'll also want to store these values on 'change'
event to fully support a dropdown. Also store scrollTop
to prevent Firefox from scrolling inside a multi-select. These are rendered as lists, not as dropdowns, causing Firefox to scroll down or up when the selected index was changed. In case of a multi-select you do not want to listen to it's 'change'
event, this will have a reversed effect.
Usage
You can use it like this:
.addEventListener('keydown', function (event) {
switch (event.which || event.keyCode) {
case 37: // left arrow
case 39: // right arrow
event.preventDefault();
ensurePreventDefault(this);
break;
}
});
JSFiddle
This expands on A1rPun's JSFiddle.
Ruud's Answer works but if you look closely or if you have a lot of code running in the event, you'll see the select value changing the next element and back to the original one.
Here's a solution that works on Firefox, and looks cleaner to me. Untested in other browsers.
The trick is simply to set the select as disabled in the keydown event, then to reenable it on the next frame with a setTimeout. The anonymous function will not run until all the code in the event handler has been processed, assuring that the select is not reenabled too early.
mySelect.addEventListener('keydown',
function (event) {
switch (event.which || event.keyCode || event.charCode) {
case 33:
this.disabled = true;
setTimeout(function (elem) {elem.disabled = false;}, 0, this);
break;
case 34:
this.disabled = true;
setTimeout(function (elem) {elem.disabled = false;}, 0, this);
break;
}
});
Here's the JSFiddle
IN regard to the answer of Ruud Lenders: works only if you have a single select in the form. If you have multiple select dropdowns then you can use the following version:
$(document).on('keydown', 'select', function(event) {
var value = $(this).find('option:selected').val();
if ((event.which == 37 || event.which === 39)) {
setTimeout(function (obj, val) {
console.log(val)
return function() {
obj.find('option[value="' + val + '"]').prop("selected", true)
}
}($(this), value), 0);
}
});
本文标签: HTMLJavascriptstop left right arrow from changing dropdown menu choiceStack Overflow
版权声明:本文标题:HTMLJavascript - stop left right arrow from changing dropdown menu choice - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745005383a2637230.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论