如何检测用户是否尝试在新标签中打开链接?

Dan*_*rov 22 javascript

我正在编写一个网站,其中所有内容都存储在JavaScript环境中,因此应该可以在"页面"之间导航而无需额外的HTTP请求.

不过,我想保留用户关于链接打开方式的意图.例如,如果Mac用户apple +点击链接,则应在新选项卡中打开它.但是如果用户想要在当前窗口中打开一个链接,我想避免发出新的HTTP请求,只需使用DOM操作来显示新内容.

这是我试过的(JSFiddle):

<a href="http://yahoo.com" id="mylink">Yahoo!</a>
Run Code Online (Sandbox Code Playgroud)
document.getElementById("mylink").onclick = function() {
    alert("clicked");
    return false;
}
Run Code Online (Sandbox Code Playgroud)

它的行为与正常的左键单击和上下文菜单操作一样,但不适用于带有修饰键的单击.我可以检查某些修改键是否被保留,但这看起来很脆弱.

Twitter的网站具有类似于我想要的行为 - 当您点击用户名时,它通常是一个AJAX请求,但如果您点击持有的元键,则会获得一个新标签.

我更喜欢没有库的普通JavaScript解决方案,除非这需要一堆特定于平台的逻辑.

更新

我看了一下GitHub的代码,它也有我所追求的行为,它确实检查了某些密钥被保留.所以我接受克里斯的回答,因为似乎没有更好的选择.

$(document).on("click", ".js-directory-link", function (t) {
    return 2 === t.which || t.metaKey || t.ctrlKey ? void 0 : ($(this).closest("tr").addClass("is-loading"), $(document.body).addClass("disables-context-loader"))
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ker 28

您可以检查ctrlKey,shiftKey以及metaKey事件对象的属性.如果其中一个为真,则保持键控制,移位或元(Apple命令)键,您应该允许默认链接操作继续.否则,您将使用preventDefault停止链接操作并使用javascript处理它.

添加target="_blank"到锚标记,因此默认链接行为是打开新选项卡.否则它将在当前页面的顶部打开(可能需要).

这是javascript,无论哪种方式:

document.getElementById("mylink").onclick = function(evnt) {
    if (
        evnt.ctrlKey || 
        evnt.shiftKey || 
        evnt.metaKey || // apple
        (evnt.button && evnt.button == 1) // middle click, >IE9 + everyone else
    ){
        return;
    }
    evnt.preventDefault();

    alert("clicked");
    return false;
}
Run Code Online (Sandbox Code Playgroud)

小提琴:http://jsfiddle.net/6byrt0wu/

文档

  • @ChrisBaker酷:)中间点击解决方案不适用于Linux上的Firefox 35,但它适用于Chromium 39.此外,它可能是一个禁止右键单击的好选项,因为从那里打开新选项卡仍然可以访问. (3认同)
  • 但这些键在某种程度上是特定于操作系统和浏览器的。我可以尝试确定哪些修饰键会导致基于“window.navigator”的新选项卡/窗口,我只是想知道是否有更好的方法。 (2认同)
  • 在没有任何点击事件的情况下在新选项卡或窗口中打开链接的情况怎么样?@Daniel——浏览器嗅探是一个糟糕的解决方案,除非当新平台出现时代码崩溃时,你会得到报酬来维护代码。 (2认同)
  • @chris——用两指轻敲,或拖动或多次单击来选择,然后使用键盘或上下文菜单进行复制。上下文菜单上还有右键单击+“打开”,它在当前窗口中打开链接并且不调度单击事件,以及各种插件和加速器。我认为关键是任何方法都是不可靠的,并且只能在某些时候起作用(并且用户可能不知道何时使用哪种方法)。此外,保持服务器页面的结果与本地页面相同似乎给站点维护人员带来了不必要的不​​便(但这是 OP 的问题)。 (2认同)