Lets say I want to intercept certain anchor element links and track them. I have the following which works.
HTML
go to foo
JS
$('a[data-mytracking]').click((event) => {
event.preventDefault();
// Do some synchronous code to log tracking
console.log(event.target.getAttribute('data-mytracking'), event.target.href);
window.location = event.target.href;
});
Is there a way to have this click code still intercept middle clicks or right click "open in a new tab"? I know I can do this if I make the href="javascript:void(0)". But then people lose the ability to open in a new tab.
Some browsers have auxclick event. You also can track event.which to track middle button.
$("a[data-mytracking]").on('click', function(ev) {
if( ev.which== 2 ) {
e.preventDefault();
// do smth else
}
});
Opening through a contextmenu is possibly not trackable, but you can have oncontextmenu event.
P.S. at least Chrome doesn't trigger click on opening a new tab with a middle button. But it does trigger mouseup.
Related
below code will trigger a popup with Reload site? or Leave site? message
on page refresh, press back button or on tab close
How to trigger this event only on tab close
window.addEventListener('beforeunload', function (e) {
// Cancel the event
e.preventDefault();
// Chrome requires returnValue to be set
e.returnValue = '';
});
There is no direct way of doing it because javascript doesen't have access to read browser actions. But if you want to do something on the server based on these actions, you may find this helpful.
When this element is middle clicked:
// Allow middle button click to open client in another tab.
$(document).on('mousedown', '.clientlist-edit', function (event) {
if (event.which === 2) {
event.preventDefault();
var url = $(this).attr('href');
url = url.toLowerCase().replace('/addedit', '/clientindex');
window.open(url, '_blank');
return false;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a class="clientlist-edit" href="/Clients/Management/AddEdit/4ffac190-72d2-476a-b0be-a9d90097272a">
<i class="glyphicon glyphicon-pencil"></i> <strong class="title">Client Name</strong>
</a>
This handler is called and when it gets to window.open, two tabs are opened. The first is the URL (variable URL) which is desired. The second is the original href set on the anchor element which is undesired. I'm calling preventDefault. What am I missing?
It is reproducible. See the link below. Sometimes it is two middle clicks. It is a middle click. It only happens in Firefox.
https://jsfiddle.net/jsmunroe/eap1b6k7/3/
I'm using Firefox 68.0.2.
I guess your goal here is to intercept the user trying to open a link in a new tab and instead open a different link in a new tab. If I'm correct, then you're going to need to adjust your strategy in a few key ways:
Don't use mousedown
Click events are triggered by a mouse-down followed by a mouse-up event. That means that normally you have to press and release the button before any click-type thing happens, whether that's navigation (left-click), context menu (right-click) or open in new tab (middle-click). If you try to simulate this using mousedown, it's gonna feel weird - the action will happen too soon!
Also, as you've now observed, it won't work correctly: the corresponding click event will still happen after your handler runs, because you're not cancelling the right event. What does your preventDefault() / return false accomplish? Well, try holding the middle button down and dragging: most browser will probably pan around the view as you move your mouse, but if you try this on your "Middle Click Me" element... Nothing happens. Yep, you've only succeeded in making your page slightly more annoying to scroll around on.
DO use the auxclick event.
I'm guessing you went with mousedown in the first place because you observed that nothing fired for a middle click when you captured the click event. A few years ago, click would've worked fine - but now, click only fires for the primary mouse button. This is a good thing! Way too many people inadvertently blocked right- and middle-clicks by capturing click, when they only intended to capture left-clicks. Presumably if you're capturing auxclick, you know what you're doing and can be trusted to handle it properly. (so, y'know... Do be careful)
The w3c actually has rather good documentation on all of this, so I'd be remiss if I didn't link to it and quote the relevant bits here:
The click event should only be fired for the primary pointer button (i.e., when button value is 0, buttons value is 1). Secondary buttons (like the middle or right button on a standard mouse) MUST NOT fire click events. See auxclick for a corresponding event that is associated with the non-primary buttons.
The click event MAY be preceded by the mousedown and mouseup events on the same element, disregarding changes between other node types (e.g., text nodes). Depending upon the environment configuration, the click event MAY be dispatched if one or more of the event types mouseover, mousemove, and mouseout occur between the press and release of the pointing device button. The click event MAY also be followed by the dblclick event.
Finally, here's your snippet with the changes above, for your review (you can't actually test it here, since window.open is blocked in Snippets - but you'll get an error indicating this and not see any tabs open; paste it into your fiddle for a real test):
// Allow middle button click to open client in another tab.
$(document).on('auxclick', '.clientlist-edit', function (event) {
if (event.which === 2) {
event.preventDefault();
var url = $(this).attr('href');
url = url.toLowerCase().replace('/addedit', '/clientindex');
window.open(url, '_blank');
return false;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a class="clientlist-edit" href="/Clients/Management/AddEdit/4ffac190-72d2-476a-b0be-a9d90097272a">
<i class="glyphicon glyphicon-pencil"></i> <strong class="title">Client Name</strong>
</a>
Yep - the only change is mousedown -> auxclick! Enjoy...
Further reading
Middle button click event
UI Events - event type click - W3C Editor's Draft
Element: auxclick event on MDN
I've a personal website where you can listen music while reading the content. After Firefox released the 66 version with the "autoplay" blocked, I'm having a lot of problems with the audio.
By the default, the audio player it's stopped so the user has to started it (and comply with the new behaviour standard that browsers want) but I've discovered that when I click on the links and it opens in a new tab target="_blank"the audio stops playing and the canvas animation also.
But I've discovered that if I open the links with the middle button of the mouse or I use Ctrl + Click the tab opens without changing to it on the background and the audio and the animation still works and don't stop.
So, I've been trying to change the default behaviour of the left click to fire a middle button or Ctrl + Click when I click on a link but I can't make it work.
I want to detect a left click on the entire document and change the behaviour to middle buttonor Ctrl + Click (but maybe this is an ugly approach) or make a function and call it on the <a> tag with the onclick=_the_function_
At the moment, I can detect the button (Reference):
$(document).onclick(function(event) {
if (event.which === 0) or (event.button === 0) {
event.stopPropagation();
event.preventDefault();
# here I want to change the pressed button
}
});
But I don't know in which variable I have to change the value of the pressed button. Or if this approach it's not the correct way.
Regards.
You could create a custom event that sets event.button and trigger that instead when the applicable links are clicked.
Something like:
$('a.someClass').click(function(e) {
if (e.button !== 1) {
e.preventDefault();
e.stopPropagation()
console.log('Prevented left')
var evt = jQuery.Event('click', {button: 1});
$(this).trigger(evt);
}
});
I have a usability concern on a web site of mine. I have a set of tabs, each containing a form. When you click on the tab link, it gives focus to the first textbox in the tab content body. Mouse-oriented people love this "feature". The problem is when keyboard-oriented users use the TAB key on their keyboard to go through the tabs. They hit enter on the tab they want to look at, the click event fires and the tab shows up, but focus is given to the textbox, adjusting their tab order completely. So when they hit tab again, they want to go to the next tab on the screen, but since focus was moved inside the form, they can't easily get to the next tab using the keyboard.
So, inside the click event I need to determine if they actually clicked on it with a mouse button. Is this possible? My first attempt was this:
$("#tabs li a").click(function(e) {
var tab = $(this.href);
if(e.keyCode != 13)
$("input:first", tab).focus();
});
But keyCode is always 0. The which property is also always 0. Please help!
Here's the solution I came up with, it's surprisingly simple. I trapped keydown on the tab links, and triggered the click event when keyCode was 13. Luckily, the trigger function allows us to pass extra parameters to the event handler...
$("#tabs li a").keydown(function(e) {
if(e.keyCode == 13) {
$(this).trigger("click", true);
e.preventDefault();
}
});
So I just had to change my click handler to receive the new parameter and use it...
$("#tabs li a").click(function(e, enterKeyPressed) {
if(enterKeyPressed)
alert("Enter key");
else
alert("Clicked");
});
I put up a demo on jsFiddle as well. Thanks to everyone who read the question.
An even simpler solution that worked for me was to just check whether there were any mouse coordinates passed with the event.
document.addEventListener('click', function(e) {
//if the event object is passed with mouse coordinates,
if(e.screenX && e.screenY){
//The mouse was clicked
}else{//The enter key was pressed}
});
Would a global "focus" variable work, which disable focus on mouse setting after tab usage on a given tab until a mouse is moved to a new block.
This would not be the feature your requesting, but I believe it might give you what your looking for.
eg. mouse hoovers option 5, you hit tab, now you store the 5 in the variable, disallowing focus to 5 until something else been focused on, but as soon something else is focused, global is turned back to -1.
Not cleanest workaround I admit that freely.
I want to do this: when you click a link on a page, it will open the link normally, but when you double click the link, it will alert the link's 'href' attribute.
However, when I try to double click a link, it will always open the link. Any idea?
The link opens after the first click of a double click, so you will need to add a time delay to determine which is which. Here's some code (using the jQuery JavaScript library for brevity) that works on all the browsers except Internet Explorer (try it out). If you can figure out why it doesn't, I'd like to know.
$('a').click(function(event) {
var elem = $(this),
clickTimeout = elem.data('clickTimeout');
if(clickTimeout) {
// Double click; cancel the single click timeout
clearTimeout(clickTimeout);
elem.data('clickTimeout', null);
alert(elem.attr('href'));
} else {
// Might be a single click; wait and see
elem.data('clickTimeout', setTimeout(function() {
// Single click; timeout was not cancelled
elem.data('clickTimeout', null);
// Navigate to the link's URL
window.location.href = elem.attr('href');
}, 500));
}
// Stops propagation and prevents default action
return false;
});
maybe it's just a typo: the event you're looking for is named ondblclick, not ondbclick.
To avoid the link being opened, you may want to work with right-clicks instead.
Because the onclick event gets fired before the ondbclick event.
That is the reson why ondblclick does not get executed -> the link gets loaded first.
This is tricky because the order of event is not the same in all browsers. Check out this article: http://unixpapa.com/js/mouse.html under the section for double clicks.
You could cancel the default action of clicking the link and write your own handler for the click event.
A double click is two clicks. Thus, it fires the click event.