0

Question

I want to trigger a (middle) mouse click on a link, in a way that triggers the native browser behavior for this event.

E.g. in those browsers I work with, middle-click will cause the linked page to open in a new tab in the background.

But if other browsers have a different behavior, that should be triggered instead.

I know there is the element.click(); method, but how do I tell it which mouse button should be clicked?

Background

The background is that I want to make a div behave as much as possible like a regular link. The idea was that I would create a hidden link tag and trigger the native browser behavior.

Requirements for the div-as-a-link:

  • href can come from a data-href attribute.
  • Native browser behavior for left-click, middle-click and possibly right-click.
  • respect of the target attribute, which could come from a data-target attribute.
  • tabindex
  • activation with the keyboard?
  • possibility to select text snippets within the div. This means we cannot just use an overlay.

Why not use a native link tag? Because the div contains inner <a> tags. So making the div box an a-tag would cause nested a-tags which would cause some browsers to restructure the DOM tree.

Obviously I could just set document.location.href on click. But this is only 20% of the browser's native behavior.

I could also try to detect the mouse button, and use js to open the tab in the background, if it was the middle button.

But maybe some browsers have a different behavior for middle-click. I would rather let the browser do its thing, than trying to replicate a specific browser behavior with js.

The idea I had was to create a hidden <a> tag with the same href, and delegate click events from the <div> to this hidden <a> tag. For this, I need to trigger the event with the same mouse button. I am not sure how to do this.

js or jQuery?

jQuery is ok for my personal use case. But to make this useful to a wider audience, maybe also post how to do it without jQuery, if you know.

See also

There are some question which deal with this kind of problem, but each of them looks at a different angle or has different constraints.

donquixote
  • 4,877
  • 3
  • 31
  • 54
  • 1
    Try this solution from another SO: http://stackoverflow.com/a/32868971 – Jon Uleis Dec 09 '16 at 17:25
  • http://stackoverflow.com/a/21224428/2694511 – Spencer D Dec 09 '16 at 17:27
  • @JonUleis Awesome! Could I simply send the existing click event from the div to the dispatchEvent(), or do I need to create a new event object? – donquixote Dec 09 '16 at 17:28
  • @SpencerDoak This tells me how to detect the mouse button but not how to trigger such an event. But anyway this is also useful. – donquixote Dec 09 '16 at 17:29
  • @SpencerDoak Your link is for detecting clicks, not triggering them like OP asked. @donquixote You'll have to experiment and see - might take a little finagling (note that they're executing the event on the `[0]` index of the jQ selector, for example). – Jon Uleis Dec 09 '16 at 17:31

2 Answers2

2

This is what I come up with thanks to @JonUleis in the comments and @MikeWillis in https://stackoverflow.com/a/32868971/246724

  $('.linkbox', context).once('linkbox').each(function(e){

    var $linkbox = $(this);
    var href = $linkbox.data('href');
    if (!href) {
      return;
    }
    var $hiddenLink = $('<a>').attr('href', href).hide().appendTo('body');
    $linkbox.click(function(e){
      $hiddenLink[0].dispatchEvent(new MouseEvent('click', {button: e.button, which: e.which}));
      e.preventDefault();
    });
  });

Note that I put the hidden link outside of the clicked div, to prevent recursion.

The right-click menu does not give me "copy link url", but I imagine this would be really hard to replicate.

UPDATE: I found that I don't really need to append the link to anything, and it still works. But I only tested this in Chromium on Linux so far.

Community
  • 1
  • 1
donquixote
  • 4,877
  • 3
  • 31
  • 54
1

This is the code to achieve left click and middle click functionality. tabindex works with any html element so you can use it not the div

$("#link").on('click', function(e) {
  const hasTargetBlank = $(this).data('target') === '_blank';
  const href = $(this).data('href');

  switch(e.which) {
    // left click
    case 1: {
      if (hasTargetBlank) {
        window.open(href);
      } else {
        window.location = href;
      }
      break;
    }
    // middle click
    case 2: {
      window.open(href);
      break;
    }
    // right click
    case 3: {
      // do what you want to do
    }
   }
});
Sagi_Avinash_Varma
  • 1,489
  • 11
  • 23