Command-click doesn't open a new tab, but middle-click does
Asked Answered
C

4

26

On my website, which is a one-page JS site using Sammy.js and jQuery, when I middle-click a link with a mouse, the link opens in a new tab. But when I command-click on a Mac, it doesn't. This happens in both Firefox and Chrome, so I assume it must be according to spec in some way.

This happens on a Macbook Air (so trackpad + command button). Most sites work just fine though, with command-click being identical to normal middle-click.

Try it out yourself: https://circleci.com. Command-click between "about", "home" and "contact" and you should experience the problem - they don't open in new tabs.

Calcimine answered 18/5, 2012 at 22:11 Comment(7)
Command-click is usually interpreted as a right-click on a Mac: is that what you are trying to intercept?Libove
I'm using windows 7 and google chrome (v19). Ctr-Click does not open a new tab. Maybe it is working as expected?Syrupy
@Libove that would be Control-Click.Alto
There are events attached to those links right? Find the difference between those three links and the login link - because that one works as expected.Hospitable
@Hospitable THe login link doesnt have a handler, but the others do. But why does it work when a mouse middle-clicks it.Calcimine
@PaulBiggar: I don't see a handler assigned to the login link when inspecting. Has it been removed since your original comment, or is it delegated etc. instead?Father
@o.v. No, the login link never had a handler.Calcimine
F
35

Speculating here, but will confirm later from a Mac. This has been confirmed to be working on a Mac.

Win ctrl+click or a Mac command+click gets picked up by a "normal" click listener, just like a click with any other modifier key (alt+click, shift+click etc).

This is particularly confusing since a ctrl+click on a Mac gets interpreted as a right-click on OS level. Command-click, on the other hand, is not interpreted as a middle-click but rather is a browser preference.

Assuming that you do not have in-site functionality that specifically relies on modified clicks, it would be appropriate to exclude such events from click listeners, and instead allow for them to bubble up to be natively handled by the browser. Given the experience of someone in the similar situation, you should be able to add the following to click handlers (likely a delegate on library level as pointed out by Brilliand):

if (e.metaKey || e.ctrlKey) return;

When added at the beginning of the handler with e referring to a current click event, this should circumvent any following e.preventDefault();

Update:

It actually works! In this rather minimalistic fiddle, I am able to recognize when command-clicked or control-clicked, so as to avoid executing the rest of the click handler which includes ajax-fetching the content and e.preventDefault();. This allows for a command-click to be handled "as intended" on a Mac, i.e. opening the link in a new tab.

With this finding in mind, these lines should now read

if (e.isDefaultPrevented() || e.metaKey || e.ctrlKey) {
    return;
}
Father answered 30/5, 2012 at 1:40 Comment(1)
You might want to also add || event.button !== 0 for middle-click. Chrome works by your example but Safari needed this extra check.Cabretta
H
6

There is some interesting insight here: https://groups.google.com/forum/#!msg/mozilla.dev.usability/H1qLTur4EFc/gXH007CAPk8J

Apparently the JS you are using can preventDefault() the cmd+click while the middle-click is unaffected. Consult the docs of your JS/Site framework.

Hospitable answered 20/5, 2012 at 3:43 Comment(0)
W
5

Here's the relevant code from sammy.js:

// bind to link clicks that have routes
$('a').live('click.history-' + this.app.eventNamespace(), function(e) {
    if (e.isDefaultPrevented()) {
        return;
    }
    var full_path = lp.fullPath(this);
    if (this.hostname == window.location.hostname && app.lookupRoute('get', full_path)) {
        e.preventDefault();
        proxy.setLocation(full_path);
        return false;
    }
});

Summary: If someone clicks on a link, override the standard link behavior with sammy.js's behavior, which is to change the current page to show the content of the target page with no actual page load. According to dakdad's link, a command-click (unlike a middle-click) is caught by the click event, and can be overridden.

For a workaround, you could remove sammy.js's event handler (using $('a').die('click.history-' + _sammy_event_namespace_);) and replace it with a modified version that checks for command-clicks and avoids overriding them.

Weeden answered 25/5, 2012 at 9:38 Comment(1)
I want to thank you for your answer, and apologize that I didn't give you the bounty. There were two good answers, but I have only one bounty to give.Calcimine
S
0

I just found this thread while searching for a solution to a similar problem. I was seeing a similar problem on the Reuters website.

Problem behavior: Some websites would intercept Command (⌘)+Click on MacOS (all browsers), and would instead navigate the current tab to the link I clicked instead of opening the clicked link in a new tab as expected.

I created a userscript which allows for Command + click to open in new tab, and prevents the current tab from changing. You can run the script with ViolentMonkey (open-source alternative to TamperMonkey), or any other preferred userscript manager.

// ==UserScript==
// @name        Force Links on All Websites to Open in New Tab When Command/Ctrl + Clicked
// @namespace   Violentmonkey Scripts
// @match       *://*/*
// @grant       none
// @version     1.0.1
// @author      Elijah Shackelford <eshack94>
// @description Forces links on all websites to open in a new tab when Command/Ctrl + Clicked, without navigating the original tab
// ==/UserScript==

document.addEventListener('click', function(event) {
    if ((event.metaKey || event.ctrlKey) && event.target.tagName === 'A') {
        event.preventDefault();
        event.stopPropagation();
        window.open(event.target.href, '_blank');
    }
}, true); // Added "true" for capturing phase, to ensure our listener acts before any others

Hopefully this helps someone in the future experiencing this same issue.

Shawm answered 7/10, 2023 at 22:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.