jQuery 下拉列表中的 keydown 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19183715/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
keydown event in drop down list
提问by Bryan
I am trying to create a Drop down list, that when a user holds the SHIFT key, it will select the same index on all other drop down lists.
我正在尝试创建一个下拉列表,当用户按住 SHIFT 键时,它将在所有其他下拉列表中选择相同的索引。
Currently, I am doing the following:
目前,我正在做以下事情:
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey });
$(document).on('change', '.report_info select', function (e) {
if (shifted) {
//Code to change other drop down lists.
}
});
This only works if you press and hold the shift key before you enter the drop down list. If you are inside the DDL and press the shift key, the keyup/keydown event will not fire and shifted
will remain false
这仅适用于在进入下拉列表之前按住 shift 键的情况。如果您在 DDL 中并按下 shift 键,则不会触发 keyup/keydown 事件shifted
并将保持false
Is there any way to catch the keyup/keydown event while a dropdownlist is focused?
有什么方法可以在下拉列表聚焦时捕获 keyup/keydown 事件?
Edit:
编辑:
Looks like it might be an issue with Chromeonly, Just tried adding the following, and it works in Firefox and IE, but not Chrome:
看起来这可能只是Chrome的问题,只是尝试添加以下内容,它适用于 Firefox 和 IE,但不适用于 Chrome:
$(document).on('keyup keydown', 'select', function (e) {
shifted = e.shiftKey;
});
Here is a fiddle of it not working in chrome: http://jsfiddle.net/ue6xqm1q/4
这是它在 chrome 中不起作用的小提琴:http: //jsfiddle.net/ue6xqm1q/4
回答by Rick Hitchcock
I think @judgeja's response may be your best bet. I'm posting this as an "answer" instead of a comment, because I've done my own research to determine that absolutely no event gets fired when a select
element is open in Chrome.
我认为@judgeja 的回应可能是你最好的选择。我将此作为“答案”而不是评论发布,因为我已经完成了自己的研究,以确定select
在 Chrome 中打开元素时绝对不会触发任何事件。
See Fiddle: http://jsfiddle.net/m4tndtu4/6/
见小提琴:http: //jsfiddle.net/m4tndtu4/6/
I've attached all possible event handlers (I think) to the input
element and both select
elements.
我已将所有可能的事件处理程序(我认为)附加到input
元素和两个select
元素。
In Chrome, you'll see many events fire when working with the input
element, but you'll see no events fire when working in the first select
element when it is open.
在 Chrome 中,您会在处理该input
元素时看到许多事件触发,但在第一个select
元素打开时处理该元素时,您将看不到任何事件触发。
Interestingly, events dofire in Chrome if the select
element has the multiple
attribute or size
>1.
有趣的是,如果元素具有属性或>1 ,Chrome 中的事件确实会触发。select
multiple
size
In Firefox, you'll see events firing on all three elements.
在 Firefox 中,您将看到在所有三个元素上触发的事件。
Outside @judgeja's suggestion, your best bet may be to simulate the select
element.
在@judgeja 的建议之外,您最好的选择可能是模拟select
元素。
回答by FrancescoMM
UPDATE
更新
Warning: Chrome (mis)behavior differs on different platforms! In Chrome Windows a keydown event is triggered right after the select is released, while on OsX it is not. This explains why @judgeja solution worked for some, and didn't for me, while mine worked on OsX and not on Windows.
警告:Chrome(错误)行为在不同平台上有所不同!在 Chrome Windows 中,释放选择后会立即触发 keydown 事件,而在 OsX 中则不会。这解释了为什么@judgeja 解决方案对某些人有效,而对我无效,而我的解决方案是在 OsX 上工作而不是在 Windows 上工作。
So I created an updated fiddle to merge my OsX solution with his Windows one.
所以我创建了一个更新的小提琴,将我的 OsX 解决方案与他的 Windows 解决方案合并。
http://jsfiddle.net/0fz5vcq6/5/
http://jsfiddle.net/0fz5vcq6/5/
On platforms where the keydown is triggered uses @judgeja solution, if it is not triggered it tests for a keyup event without the previous keydown (my previous solution). It is ugly as it works only after RELEASE of the shift key, but ugly only on Chrome OsX.
在触发 keydown 的平台上使用 @judgeja 解决方案,如果它没有被触发,它会测试没有先前 keydown 的 keyup 事件(我以前的解决方案)。它是丑陋的,因为它只有在按下 shift 键后才能工作,但只有在 Chrome OSX 上才丑陋。
var shifted = false;
var hackytimer = 0;
var lastval=null;
$(document).keydown(function(e){
if(e.which == 16){
if(Date.now() - hackytimer <200){
alert("you pressed shift inside the select (Win)");
changeAllSelects($(this).val());
} shifted = true;
}
});
$(document).keyup(function(e){
if(e.which == 16) {
if(!shifted && lastval!=null) {
alert("you pressed shift inside the select (OsX)");
$('.report_info select').each(function () {
changeAllSelects(lastval);
});
}
shifted = false;
}
});
$(document).on('change', '.report_info select', function (e) {
hackytimer = Date.now();
if (shifted) {
changeAllSelects($(this).val());
} else {
lastval=$(this).val();
}
});
function changeAllSelects(cr){
hackytimer = 0;
$('.report_info select').each(function () {
$(this).val(cr);
});
}
Credit goes mainly to @judgeja for his timer solution with some added workaround for the Mac (and other platforms that behave the same)
主要归功于@judgeja 的计时器解决方案,并为 Mac(以及其他表现相同的平台)添加了一些解决方法
I still think emulating the selects with something HTML like http://gregfranko.com/jquery.selectBoxIt.js/is cleaner as they should not interfere with keydown/keyups.
我仍然认为用像http://gregfranko.com/jquery.selectBoxIt.js/这样的 HTML 来模拟选择更干净,因为它们不应该干扰 keydown/keyups。
PREVIOUS SOLUTION (OsX only)
以前的解决方案(仅限 OSX)
The only solution I could think of, in the total absence of any event, is to test if a shift up occurred without the previous shift down. This may work if you don't have other elements that behave the same way as the selects
在完全没有任何事件的情况下,我能想到的唯一解决方案是测试是否在没有先前降档的情况下发生了升档。如果您没有其他与选择行为相同的元素,这可能会起作用
It is a bit tricky and dirty, will work AFTER the user releases the shift key
这有点棘手和肮脏,将在用户释放 shift 键后工作
var shifted = false;
var lastval=null;
$(document).keydown(function(e){
if(e.which == 16){
shifted = true;
}
});
$(document).keyup(function(e){
if(e.which == 16){
if(!shifted && lastval!=null) {
alert("you pressed shift inside the select");
$('.report_info select').each(function () {
$(this).val(lastval);
});
}
shifted = false;
}
});
$(document).on('change', '.report_info select', function (e) {
var cr = $(this).val();
if (shifted) {
$('.report_info select').each(function () {
$(this).val(cr);
});
} else {
lastval=cr;
}
});
Should behave normally on non buggy browsers. Anyway I agree emulating the selects with something HTML like http://gregfranko.com/jquery.selectBoxIt.js/might be the cleaner way.
应该在没有错误的浏览器上正常运行。无论如何,我同意用像http://gregfranko.com/jquery.selectBoxIt.js/这样的 HTML 来模拟选择可能是更干净的方式。
回答by MCSharp
Your syntax looks incorrect.
您的语法看起来不正确。
$("#target").keydown(function() {
alert( "Handler for .keydown() called." );
});
回答by James
This is a pretty hacky solution to be honest, but it's a means to an ends until you hopefully find something better.
老实说,这是一个非常棘手的解决方案,但它是达到目的的一种手段,直到您希望找到更好的方法。
Since the problem is chrome doesn't register the keydown/keyup events on the select
elements until after the dropdownlist has disappeared, we need to either
由于问题是select
在下拉列表消失之前,chrome 不会在元素上注册 keydown/keyup 事件,我们需要要么
a)figure out how to make the event fire (I've no idea)
a)弄清楚如何触发事件(我不知道)
or
或者
b)check if our conditions were met in a different order.
b)检查我们的条件是否以不同的顺序满足。
Chrome will fire the shift keypress event after click, so we can simply check if click was pressed immediately before this event. Since other browsers behave more expectedly we'll also leave the previous code in place.
Chrome 将在点击后触发 shift keypress 事件,因此我们可以简单地检查是否在此事件之前按下了点击。由于其他浏览器的行为更符合预期,我们也将保留之前的代码。
To do this we set a timer on the click event, and then when the shift event for the select is fired, if the click event timer was also just set we should run our code here so that chrome will fire it. We reset the timer then so that it isn't fired multiple times.
为此,我们在Click事件上设置一个计时器,然后在触发SELECT的换档事件时,如果单击“事件计时器”也只是设置,我们应该在此处运行我们的代码,以便Chrome将触发。然后我们重置计时器,这样它就不会被多次触发。
NOTE: if you press shift immediately after setting the values (within whatever limit from the click you specify), it will also set them all. I don't think this is unreasonable as it actually feels quite natural when it happens.
注意:如果您在设置值后立即按下 shift(在您指定的单击的任何限制内),它也会设置所有值。我不认为这是不合理的,因为它发生时实际上感觉很自然。
I used the following code:
我使用了以下代码:
var shifted = false;
var hackytimer = 0;
$(document).on('keyup keydown', function (e) {
shifted = e.shiftKey;
});
$(document).on('keyup keydown', 'select', function (e) {
shifted = e.shiftKey;
if(Date.now() - hackytimer <200){
changeAllSelects($(this).val());
}
});
$(document).on('change', '.report_info select', function (e) {
hackytimer = Date.now();
if (shifted) {
changeAllSelects($(this).val());
}
});
function changeAllSelects(cr){
hackytimer = 0;
$('.report_info select').each(function () {
$(this).val(cr);
});
}
See working example here: http://jsfiddle.net/0fz5vcq6/2/
请参阅此处的工作示例:http: //jsfiddle.net/0fz5vcq6/2/
回答by gdyrrahitis
First of all. You should pick an event to register. Don't register to keyup and keydown the same time. You give the browser a hard time, because they affect your end result. To see what I mean, just edit the plunk, add a keyup event. The end result behaves a little sloppy.
首先。您应该选择一个事件进行注册。不要同时注册 keyup 和 keydown。你给浏览器带来了困难,因为它们会影响你的最终结果。要明白我的意思,只需编辑 plunk,添加一个 keyup 事件。最终结果表现得有点草率。
keyup: Event fired when a key is released on the keyboard.
keyup:在键盘上释放键时触发的事件。
keydown: Event fired when a key is pressed on the keyboard.
keydown:在键盘上按下某个键时触发的事件。
keypress: Event fired when a key is pressed on the keyboard.
keypress:在键盘上按下某个键时触发的事件。
They have their differences, better stick to one, I prefer for this example to use keydown, just plays better with me, you can use keyup.
他们有他们的不同,最好坚持一个,我更喜欢这个例子使用keydown,只是和我玩得更好,你可以使用keyup。
Edit: A quick note. The keyup for my example doesn't play well, because it seems, change in the selectedIndex, comes first and then the binded event. On keydown, first the event fires, does it's work and then the selectedIndex changes. To play with keyup, the code below needs some modification, that means the step is not needed, when you use keyup
编辑:快速说明。我的示例中的 keyup 效果不佳,因为似乎 selectedIndex 中的更改首先出现,然后是绑定事件。在 keydown 上,首先触发事件,它是否起作用,然后 selectedIndex 发生变化。玩keyup,下面的代码需要一些修改,这意味着不需要步骤,当你使用keyup
I have a plnkr demo here.
我这里有一个 plnkr 演示。
I've tested it on IE10, Opera, Safari, Firefox and Chrome. As you might expect, webkit browsers, don't fire the keydown/keyup/keypress event when a select list has focus. Reason unknown for me, at the moment. In Firefox works great. On IE works partially. So, in order to achieve your goal, custom code to the rescue! I just binded a change event to the document, i hear for kewdown and change. If the event type is change, then the workaround comes into play. Here some code:
我已经在 IE10、Opera、Safari、Firefox 和 Chrome 上对其进行了测试。As you might expect, webkit browsers, don't fire the keydown/keyup/keypress event when a select list has focus. 原因我不知道,目前。在 Firefox 中效果很好。在 IE 上部分工作。因此,为了实现您的目标,自定义代码来拯救您!我刚刚将更改事件绑定到文档,我听到了 kewdown 和更改。如果事件类型发生变化,则变通方法开始发挥作用。这里有一些代码:
$(document).ready(function(){
$(document).on('keydown change', 'select', function(evt){
var shiftKey = evt.shiftKey;
var code = evt.keyCode || evt.which;
//if it's a change event and i dont have any shiftKey or code
//set the to a default value of true
if(evt.type === 'change' && !shiftKey && !code){
//special! only when change is fired
shiftKey = true;
code = true;
}
//if shift key
if(shiftKey && (code === 40 || code === 38 || code === true)){
var target = $(evt.target);
//if code is not true means it is not a change event, go ahead and set
//a step value, else no step value
var step = (code !== true) ? (code === 40) ? 1 : -1 : 0;
var index = target[0].selectedIndex + step;
//just to keep the lower and upper bound of the select list
if(index < 0){
index = 0;
}else if(index >= target[0].length){
index = target[0].length - 1;
}
//get all other select lists
var allOtherSelects = target.closest('div').siblings('div').children('select');
//foreach select list, set its selectedIndex
$.each(allOtherSelects, function(i, el){
el.selectedIndex = index;
});
}
});
});
回答by O-mkar
Hop this thing help you out.. :)
跳这个东西帮助你.. :)
var onkeydown = (function (ev) {
var key;
var isShift;
if (window.event) {
key = window.event.keyCode;
isShift = window.event.shiftKey ? true : false;
} else {
key = ev.which;
isShift = ev.shiftKey ? true : false;
}
if ( isShift ) {
switch (key) {
case 16: // ignore shift key
break;
default:
alert(key);
// do stuff here?
break;
}
}
});
回答by user3520445
I found a very unique solution to this issue specifically for Chrome. It appears Chrome shifts outside the normal dom for select elements when they have focus so you never get the onkey(down|press|up) events to capture the keycode. However if the size of the select box is >1 then it works. But anyone who wants an actual drop down box instead of what looks like a combo box can solve this issue with this code. In my case I was trying to prevent the backspace key from going back to the previous browser page.
我为这个问题找到了一个非常独特的解决方案,专门针对 Chrome。当普通DOM外部出现Chrome在普通的DOM外部移动时,选择元素的焦点,因此您永远不会获取onkkey(upd | up | up | up)捕获键码。但是,如果选择框的大小大于 1,则它可以工作。但是任何想要实际下拉框而不是看起来像组合框的人都可以使用此代码解决此问题。就我而言,我试图阻止退格键返回上一个浏览器页面。
Javascript looks like this:
Javascript 看起来像这样:
$(document).ready(function() {
$('select').keypress(function(event)
{ return cancelBackspace(event) });
$('select').keydown(function(event)
{ return cancelBackspace(event) });
});
function cancelBackspace(event) {
if (event.keyCode == 8) {
return false;
}
}
Then HTML looks like this:
然后 HTML 看起来像这样:
<select id="coaacct" style="border:none;width:295px;" onclick="if (this.size){this.size=''}else{this.size='20'};">
<select id="coaacct" style="border:none;width:295px;" onclick="if (this.size){this.size=''}else{this.size='20'};">
I use the onclick event to change the size of the select box to 20 if it has no size and change it back to nothing if it has a size. This way it functions like a normal select dropdown but because it has a size greater than 1 when you are selecting the option it will detect keycodes. I didn't see this answered adequately anywhere else so I thought I would share my solution.
如果没有大小,我使用 onclick 事件将选择框的大小更改为 20,如果有大小,则将其更改回无。这样它的功能就像一个普通的选择下拉菜单,但是因为当您选择该选项时它的大小大于 1,它将检测键代码。我在其他任何地方都没有看到这个问题的充分回答,所以我想我会分享我的解决方案。
回答by Deep
Chrome hack: You can set custom event for document. And firing this event when press the shift key inside the DDL. Jquery firing trigger can pass custom params.
Chrome hack:您可以为文档设置自定义事件。并在 DDL 中按下 shift 键时触发此事件。Jquery 触发触发器可以传递自定义参数。
回答by Mayank
Check the working JS FIDDLER
检查工作的JS FIDDLER
Try the following script for your scenario
为您的场景尝试以下脚本
<script type="text/javascript" language="javascript">
window.shifted = false;
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey; });
$(document).on('change', 'select.report_info', function (e) {
var cr = $(this).val();
if (shifted) {
$('.report_info').each(function () {
$(this).val(cr);
});
}
});
</script>
回答by Vinod Kumar
Bryan, you can try the following way to do this. I tested on Jsfiddle it working in your way If I got your question correctly.
布莱恩,你可以尝试以下方法来做到这一点。我在 Jsfiddle 上进行了测试,如果我正确回答了你的问题,它会按照你的方式工作。
var shifted = false;
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey; });
$("select").on('keyup keydown', function (e) {
shifted = e.shiftKey;
});
$('.report_info select').on('change', function (e) {
var cr = $(this).val();
if (shifted) {
$('.report_info select').each(function () {
$(this).val(cr);
});
}
});
Please let me know if it works for you.
请让我知道它是否适合您。