Ctrl+click on links with click handlers - javascript

I have a link (anchor) that has an href attached to it to navigate to a specific URL say 'www.bla.com'.
<a href='http://www.bla.com' />
I also have an click handler attached to the link that performs some actions and then opens an html view in the same window. Everything works perfectly well.
However, when the user uses 'ctrl+click' to open the link in a new tab/window, the click handler seems to be taking precedence and opens the html view in the same window. But I want to retain the 'ctrl+click' behavior and allow the user open the link in a new tab/window (just as a normal link). How could I do that?
Thanks in advance!

function process(e){
var evt = e ? e:window.event;
if(evt.ctrlKey)
alert("ctrlClicked");
}​
evt.ctrlKey will return true if control key is pressed, you can write your conditions within "if" block, I tested this for chrome and ff only.

Perhaps something like this?
function onclick(e){
var event = e ? e:window.event;
this.target = event.ctrlKey?"_blank":"_self";
}​

The associated click event object will have its ctrlKey property set to true if the control key (or equivalent) was pressed when the click occurred. Check the event object and if the control key was pressed, don't do the "HTML view" thing.
Click me!
However, if the user activates the link some other way, you may or may not get a click event.
e.g.
right button -> "open in new tab/window" - no click event (Firefox, IE)
Tab to focus on link, press enter - dispatches click event (Firefox, IE)

<a target="_blank" href='http://www.bla.com' />
Add target="_blank" within to anchor tag.

Related

window.open with _blank opens two tabs in Firefox

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

capture "open link in new tab" and "Open link in new window" event

This is my code
<a href="javascript:void(0)" onclick="myFun('www.google.com');" onmousedown="myFun('www.google.com');">
whenever I am clicking on this link my function gets called using onclick event. I added onmousedown event for right-click capturing. But the problem is, this function gets called before selecting "Open in new tab" or "Open in new window" options. When the user uses right-click and before selecting the right-click options, the function gets called. I don't want this behavior. I want to call this function when the user actually selects "Open link in new tab" or "Open link in new window" options.
I don't want to show links in the status bar and also don't want to allow the user to copy the link address. That is why I used onclick and onmousedown events.
Please help me out. Thanks
The problem you have is that both, right and left click is handled with the onclick function. Another possibility would be to use oncontextmenu (as mentioned here).
But I think you need to handle right click and left click differently, so onclick is the right event, just check there if it was the primary (0) or secondary (2) mouseButton (see here). So you solution could be something like this:
myFun(link) {
var buttonPressed = instanceOfMouseEvent.button;
if (buttonPressed == 0) {
//Handle normal click
} else if (buttonPressed == 2) {
//Handle right click
}
}
It sounds like you're looking for something like this, that will change the link once the context menu is launched:
function myFun2(url) {
linkEl.href = url;
}
Then assign the a element an ID (i.e. "linkEl"), remove the onmousedown handler, and assign an oncontextmenu handler, like:
oncontextmenu="myFun2('www.google.com');"
Then when the context menu is launched, the link will change, so if "Open in New Tab" or "Open in New Window" is selected, it will go to Google (in this example) instead of whatever the link was set to previously.

jQuery event when clicked AND link

The title is a bit confusing but here's what I want to do -> There's a picture. When you click on it, a lightbox pops up (I already have that event). However, if you right click it and open in a new tab, I want a page to appear. Instagram has something similar to what I'm looking for. <a href=""> doesn't work - it executes both (launches the lightbox and redirects). How do I do that? Is there a way to cancel the href? Thanks.
EDIT: Here's a visual: http://jsfiddle.net/9VFGS/. In that case, I only want the alert() to be invoked when I click on it, but when I open it in a new tab, I want it to navigate to google.com.
Using event.preventDefault() (doc) in the event handler for triggering your lightbox will prevent the link from executing and changing your window location. Right-click context actions should still work, though, because they don't trigger click events.
$( '#my-link' ).on( 'click', function( event ) {
event.preventDefault();
// do my lightbox stuff here
}
Yes, set href="..." to href="#".

Link to anchor (ajax url) doesn't call onBeforeUnload

I have an onbeforeunload event :
$().ready(function() {
window.onbeforeunload=function() { return "haha" };
});
And my links are like this (ajax web site) :
<a href="#pageX" />
But the onbeforeunload is never called. What can i do ?
Thanks
I'm guessing since you're trying to bind to the onbeforeunload and return a string, that you're looking to provide the user with an "Are you sure you want to leave this page" dialog on an AJAX site.
In which case you probably need to go about this a little differently by binding a click handler onto the links. So you can prevent the hash change until the confirmation is made.
Something like:
$('a[href^="#"]').live('click',function(e){
if( //should we be confirming first? ) {
//put your confirmation code here either using default JS windows or your own CSS/jQueryUI dialog boxes
// this code should either cache the url of the link that was clicked and manually update the location with it when the user confirms the dialog box (if you're using JQUI windows) or simply use JS confirmation boxes and based on the response, all you need to do is return; and the link click will handle normally
e.preventDefault(); //prevent the link from changing the hash tag just yet
e.stopImmediatePropagation(); //prevent any parent elements from firing any events for this click
}
} );
Don't get me wrong, but are you serious ?
That link just refers a hash-tag, hence, it will not leave the current site and there will be no call to onbeforeunload nor unload.
If there is any *click event handlerbound to that anchor aswell, there must be something in the event handler code which really forces the current site to get unloaded (location.href` for instance).
If you just switch HTML via Ajax, there is no onbeforeunload aswell.
You could bind a handler to the onhashchange event (check browser compatibilty) but that would fire for any change that happens in your url/hash.
You're probably looking for the onhashchange event:
https://developer.mozilla.org/en/DOM/window.onhashchange

How to determine if onbeforeunload has been caused by clicking a link in Chrome

The problem is as follows.
onbeforeunload works like a charm in Firefox and has e.explicitOriginalTarget.activeElementthat shows what element has been clicked to cause it.
window.onbeforeunload = function(e){
if (e.explicitOriginalTarget.activeElement){
return;
}
In Chrome the 'e' object looks identical when you close the window or click the link.
Is there any way to determine the target in chrome?
Late response, I know, but you can always try this (confirmed working in IE):
target = document.activeElement;
alert(target.href);
Just showing you that you can grab the active element and then just parse the href to figure out what is happening.
Another option:
$("a").on("click", function(){
window.last_clicked = $(this);
});
Then simply refer to last_clicked from within your onbeforeunload handler. This is the best cross-browser compatible solution I've found, since document.activeElement is unreliable.
No. The target of the event is the window or document, not the link. Unlike Firefox, Chrome provides no helpful bonus properties on the event object. Your best bet may be to have an click event handler on the body that examines the event target to see if it's a link, but that's not foolproof: the link may have its own click event handler that prevents the default action, or the user may follow the link using the keyboard, in which case no click event will be fired.

Categories

Resources