JQuery或JavaScript:如何确定在单击锚标签超链接时是否按下Shift键?

99

我有一个调用JavaScript函数的锚点。

无论是否使用jQuery,我该如何确定在单击链接时Shift键是否按下?

以下代码不起作用,因为只有在按下“真实键”(而不是Shift键)时才会触发keypress事件。(我希望它会在仅按下Shift键时触发。)

var shifted = false;

$(function() {                           
    $(document).keypress(function(e) {
        shifted = e.shiftKey;
        alert('shiftkey='+e.shiftkey);
    });

    $(document).keyup(function(e) {
        shifted = false;
    });
}

...

function myfunction() {
  //shift is always false b/c keypress not fired above
}

4
以下代码也无法运行,因为您输入的是 shiftkey 而不是 shiftKey :-) - Simon_Weaver
如果您需要了解如何避免在按下 shift+click 时调用处理程序,请使用 filter-altered-clicks - fregante
12个回答

111
    $(document).on('keyup keydown', function(e){shifted = e.shiftKey} );

22
这对我有用,但打断了所有不涉及 shift 的标准快捷键,因为该函数返回 false。我需要显式地 return true 以允许使用 crtl+r、ctrl+s、ctrl+p 等快捷键。 - John H
4
建议使用keydown而不是keypress。 - rwitzel
@rwitzel 的 keydown 和 keyup 允许您跟踪 shift 键的实际状态,因为它们会针对键盘上的每个键触发。Keypress 并不总是被触发,例如仅按下 shift 键时不会触发。 - jakubiszon
@Gerry 这可能是因为您的页面上有其他事件处理程序导致事件链断开。首先在一个空白/新页面上检查(不包括所有脚本的页面)-它将完美地工作。 - jakubiszon
$(document).keyup(function (e) { } 和 $(document).keydown(function (e) { } 对我很有用。 - Gerry
显示剩余2条评论

81

以下是JavaScript中每个按键的关键代码。您可以使用它来检测用户是否按下了Shift键。

backspace           8
tab                 9
enter               13
shift               16
ctrl                17
alt                 18
pause/break         19
caps lock           20
escape              27
page up             33
page down           34
end                 35
home                36
left arrow          37
up arrow            38
right arrow         39
down arrow          40
insert              45
delete              46
0                   48
1                   49
2                   50
3                   51
4                   52
5                   53
6                   54
7                   55
8                   56
9                   57
a                   65
b                   66
c                   67
d                   68
e                   69
f                   70
g                   71
h                   72
i                   73
j                   74
k                   75
l                   76
m                   77
n                   78
o                   79
p                   80
q                   81
r                   82
s                   83
t                   84
u                   85
v                   86
w                   87
x                   88
y                   89
z                   90
left window key     91
right window key    92
select key          93
numpad 0            96
numpad 1            97
numpad 2            98
numpad 3            99
numpad 4            100
numpad 5            101
numpad 6            102
numpad 7            103
numpad 8            104
numpad 9            105
multiply            106
add                 107
subtract            109
decimal point       110
divide              111
f1                  112
f2                  113
f3                  114
f4                  115
f5                  116
f6                  117
f7                  118
f8                  119
f9                  120
f10                 121
f11                 122
f12                 123
num lock            144
scroll lock         145
semi-colon          186
equal sign          187
comma               188
dash                189
period              190
forward slash       191
grave accent        192
open bracket        219
back slash          220
close braket        221
single quote        222

并非所有的浏览器都能很好地处理keypress事件,因此请使用keyup或keydown事件,例如:

$(document).keydown(function (e) {
    if (e.keyCode == 16) {
        alert(e.which + " or Shift was pressed");
    }
});

2
使用 event.key 替代!它会直接给你字符,例如:"a"、"1"、"LeftArrow"。 - Gibolt
在其VanillaJS版本中更好:document.addEventListener("keydown", function(e){ console.log(e.which); }); - Evgeny

30
对于鼠标事件,我知道至少在Firefox中,事件对象上的“shiftKey”属性将告诉您Shift键是否按下。这在MSDN上有记录,但我已经很久没有尝试过了,所以我不记得IE是否处理正确。
因此,在您的“click”处理程序中,应该能够检查事件对象上的“shiftKey”。

2
确实如此。这一点可以追溯到 JavaScript 最早的日子。 - bobince

23

我遇到了类似的问题,试图捕获“shift+click”事件,但由于我使用了一个带有回调的第三方控件而不是标准的click处理程序,因此我无法访问事件对象及其相关的e.shiftKey属性。

最终,我通过处理鼠标按下事件来记录Shift键是否按下,并在后面的回调中使用它。

    var shiftHeld = false;
    $('#control').on('mousedown', function (e) { shiftHeld = e.shiftKey });

为了防止其他人在搜索解决此问题的方法时也会跑到这里,我发表一下。


10

要检查是否在使用鼠标点击时按下了shift键,可以通过click事件对象中的确切属性shiftKey(还有ctrl、alt和meta键)来实现:

https://www.w3schools.com/jsref/event_shiftkey.asp

因此可以使用jQuery:

$('#anchor').on('click', function (e) {
    if (e.shiftKey) {
        // your code
    }
});

7

我使用了一种方法来测试是否有任何特定键被按下,该方法通过将当前按下的键代码存储在数组中实现:

var keysPressed = [],
    shiftCode = 16;

$(document).on("keyup keydown", function(e) {
    switch(e.type) {
        case "keydown" :
            keysPressed.push(e.keyCode);
            break;
        case "keyup" :
            var idx = keysPressed.indexOf(e.keyCode);
            if (idx >= 0)
                keysPressed.splice(idx, 1);
            break;
    }
});

$("a.shifty").on("click", function(e) {
    e.preventDefault();
    console.log("Shift Pressed: " + (isKeyPressed(shiftCode) ? "true" : "false"));
});

function isKeyPressed(code) {
    return keysPressed.indexOf(code) >= 0;
}

Here is the jsfiddle


4
这个解决方案很棒,但在keyup上需要进行微小修复:while (idx >= 0) { keysPressed.splice(idx, 1); idx = avpg.keysPressed.indexOf(e.keyCode); } 否则,只有第一次按键被移除。为了注意到这一点,可以按住Shift几秒钟。数组会填满Shift代码,但只有一个会在keyup时被移除。 - pkExec
或者补丁:case "keydown": { 如果(!this.keysPressed.includes(e.keyCode)){ this.keysPressed.push(e.keyCode); } break; } - Matěj Štágl

7
keypress事件并非在所有浏览器中都会被触发,当您点击shiftctrl时也有可能不会被触发,但是幸运的是,有一个可以被触发的 keydown事件。 如果您将keypress替换为keydown,则可能会更好地解决问题。

1
好的,但问题是他不确定Shift键是否被按下。哦,但我想如果“keyUp”标志也被设置了,那么就可以检测到“click”被键事件括起来的情况。 - Pointy

4
优秀的JavaScript库KeyboardJS可以处理包括SHIFT键在内的所有类型按键。它甚至允许指定按键组合,例如先按下CTRL+x,然后再按a键。
KeyboardJS.on('shift', function() { ...handleDown... }, function() { ...handleUp... });

如果你想要一个简单版本,请查看@tonycoupland的回答:
var shiftHeld = false;
$('#control').on('mousedown', function (e) { shiftHeld = e.shiftKey });

@downvoters:请留下评论说明您为什么要点踩。 - koppor

3
这对我非常有效:
function listenForShiftKey(e){
    var evt = e || window.event;
    if (evt.shiftKey) {
      shiftKeyDown = true;
    } else {
      shiftKeyDown = false;
    }
}

2
更模块化的方法加上在监听器中保持this作用域的能力:
var checkShift = function(fn, self) {
  return function(event) {
    if (event.shiftKey) {
      fn.call(self, event);
    }
    return true;
  };
};

$(document).on('keydown', checkShift(this.enterMode, this));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接