JavaScript Link Element over Image - javascript

I am trying to intercept all a link clicks to do some extra work and this works fine for standalone a links but when it contains an img for example the img tag is returned instead.
JSFiddle
Is there a way to check if the element above is also an a link or is there a different way I should be handling this?
JS :
document.onclick = function (e) {
e = e || window.event;
var element = e.target || e.srcElement;
if (element.tagName == 'A') {
window.open(element.href, "_system");
return false;
}
};

you can traverse up the parent of the clicked node to see if an ancestor is an A tag
...
var element = e.target || e.srcElement;
while (element.tagName != 'A' && element.parentNode) {
element = element.parentNode;
}
if (element.tagName == 'A') {
...

You can attach the handler on the click event of the anchor tags instead of on the whole document, then you will not need to check for the event target.
var anchorTags = document.getElementsByClassName("classname");
var myEventHandler = function() {
// stuff
};
for (var i = 0; i < anchorTags.length; i++) {
anchorTags[i].onclick = myEventHandler;
}

I'm not sure if you need to actually capture all clicks, but if you're looking to capture the anchor tag that was actually clicked, you might consider the approach below.
var anchors = document.getElementsByTagName('a');
for(var i = 0, anchor; anchor = anchors[i]; i++ ) {
anchor.addEventListener('click', function (e){
e = e || window.event;
//Grabs the element that initiated the event, the anchor tag.
var element = this;
alert(element.tagName);
if (element.tagName == 'A') {
window.open(element.href, "_system");
return false;
}
})
}

You should add another condition to check if the current clicked element is a child of a element.
You could use closest method.
The Element.closest() method returns the closest ancestor of the current element (or the current element itself) which matches the selectors given in parameter. If there isn't such an ancestor, it returns null.
The condition will be like following :
if (element.tagName == 'A' || element.closest('a') != null) {
window.open(element.closest('a').href, "_system"); //Using the parent a link `href`
return false;
}
Hope this helps.
document.onclick = function (e) {
e = e || window.event;
var element = e.target || e.srcElement;
if (element.tagName == 'A' || element.closest('a') != null) {
alert("Open with href :"+element.closest('a').href);
return false;
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<p>The below Google text link returns A when clicked, correct!</p>
Google Link
<br />
<p>The below Bing image link returns IMG when clicked, incorrect!</p>
<img src="data:image/png;base64,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" />
</body>

Related

Javascript document event on certain css class

I'm used to writing in jQuery for selecting by class, however the following I can't quite get the code right. This lives on every page and should just intercept links with the class 'download-link'. The following works for all links. But i want to target it just for download-link css.
document.onclick = function (e) {
e = e || window.event;
var element = e.target || e.srcElement;
if (element.tagName == 'A') {
window.open(element.href, "_blank", "location=yes,toolbar=yes,toolbarposition=top");
return false;
}
};
I can't quite work out the selector for my if statement to change element.tagName to be element.class or similar.
Heres the last thing I tried
document.getElementById("download-link").addEventListener("click", function(e) {
window.open(e.href, "_blank", "location=yes,toolbar=yes,toolbarposition=top");
return false;
e.preventDefault();
});
You mention
should just intercept links with the class 'download-link'
though use .getElementById(). You can use .querySelectorAll() with selector ".download-link" and NodeList.prototype.forEach() to perform a task, see forEach method of Node.childNodes?. For example, attach an event listener, to each ".download-link" element
document.querySelectorAll(".download-link")
.forEach(function(element) {
element.addEventListener("click", function(event) {
// do stuff
})
})
If NodeList.prototype.forEach() is not defined at browser you can use for loop to achieve same result
for (var i = 0, nodes = document.querySelectorAll(".download-link");
nodes && i < nodes.length; i++) {
nodes[i].addEventListener("click", function(event) {
// do stuff
})
}

Javascript Open all links on _blank Except

I am using this code below to open all links on _blank pages and it works great!
I just have one problem.
How can I make it so a specific link or class is ignored by the script?
Here's the code:
<script>
document.onclick = function (e) {
e = e || window.event;
var element = e.target || e.srcElement;
if (element.tagName == 'A') {
window.open(element.href, "_blank", "location=yes");
return false; // prevent default action and stop event propagation
}
};
</script>
To ignore specific classes, use the below:
document.onclick = function (e) {
e = e || window.event;
var element = e.target || e.srcElement;
if (element.tagName == 'A' && !element.classList.contains('noBlank')) {
window.open(element.href, "_blank", "location=yes");
return false; // prevent default action and stop event propagation
}
};
<p>BBC should not be _blank</p>
Google
<br />
Yahoo
<br />
<a class="noBlank" href="http://www.bbc.co.uk">BBC</a>

How to get href of anchor when the event.target is HTMLImageElement?

I want to get the href of an anchor element when it is clicked.
I am using the following javascript code:
document.addEventListener('click', function (event)
{
event = event || window.event;
var el = event.target || event.srcElement;
if (el instanceof HTMLAnchorElement)
{
console.log(el.getAttribute('href'));
}
}, true);
This works perfectly for an embedded anchor such as this:
<div><p><a href='link'></a></p><div>
But it doesn't work when I am working with an anchor and an image:
<div><a href='link'><img></a></div>
The event.target is returning the image instead of the anchor.
The javascript code can be amended with the following if case to get around this:
document.addEventListener('click', function (event)
{
event = event || window.event;
var el = event.target || event.srcElement;
if (el instanceof HTMLImageElement)
{
// Using parentNode to get the image element parent - the anchor element.
console.log(el.parentNode.getAttribute('href'));
}
else if (el instanceof HTMLAnchorElement)
{
console.log(el.getAttribute('href'));
}
}, true);
But this doesn't seem very elegant and I'm wondering if there is a better way.
!IMPORTANT!
NOTE: Keep in mind, I have no access to an ID or class, or any other traditional identifier for that matter. All I know is that there will be an anchor clicked and I need to get its href. I don't even know where it will be, if it exists or will be created later.
EDIT: Please no jQuery or other javascript libraries.
Instead of looping all anchors in the DOM, lookup from the event.target element.
Using JavaScript's .closest() MDN Docs
addEventListener('click', function (event) {
event.preventDefault(); // Don't navigate!
const anchor = event.target.closest("a"); // Find closest Anchor (or self)
if (!anchor) return; // Not found. Exit here.
console.log( anchor.getAttribute('href')); // Log to test
});
<a href="http://stackoverflow.com/a/29223576/383904">
<span>
<img src="//placehold.it/200x60?text=Click+me">
</span>
</a>
<a href="http://stackoverflow.com/a/29223576/383904">
Or click me
</a>
it basically works like jQuery's .closest() which does
Closest or Self (Find closest parent... else - target me!)
better depicted in the example above.
Rather than adding a global click handler, why not just target only anchor tags?
var anchors = document.getElementsByTagName("a");
for (var i = 0, length = anchors.length; i < length; i++) {
var anchor = anchors[i];
anchor.addEventListener('click', function() {
// `this` refers to the anchor tag that's been clicked
console.log(this.getAttribute('href'));
}, true);
};
If you want to stick with the document-wide click handler then you could crawl upwards to determine if the thing clicked is-or-is-contained-within a link like so:
document.addEventListener('click', function(event) {
event = event || window.event;
var target = event.target || event.srcElement;
while (target) {
if (target instanceof HTMLAnchorElement) {
console.log(target.getAttribute('href'));
break;
}
target = target.parentNode;
}
}, true);
This way at least you'd avoid writing brittle code that has to account for all of the possible types of anchor-children and nested structure.

How to prevent all link (which have a span tag in it) to open?

I'm using window.onclick code to get all (current and future) anchor and apply my custom code, which does work -
window.onclick = clickEvent;
function clickEvent(e){
e = e || window.event;
var t = e.target || e.srcElement
console.log(t);
if ( t.name || t.href ){
if( typeof t.href == "string" && (t.href.substr(0,4) == 'http' || t.href.substr(0,5) == 'https') ){
if( t.attributes.href.value !== "#" ){
alert('The url is - '+t.href);
}
e.preventDefault;
return false; // no further action for this click
}
}
return true; // process click as normal
}
But when a <a> tag have a <span> tag inside of it - it doesn't work. The link open as usual.
<span>Test Url</span>
Here is the JSfiddle to check it out - http://jsfiddle.net/aajahid/3edcfm12/
And the reason is - the t (e.target) variable returns the <span> tag, not the <a> tag. For this reason I don't see any way to prevent the url to open and apply my custom function to it.
Question is - how can I prevent those links with span (or any other tag) to open?
The trick is to check for a span and if present, set your variable t to the parent, like so:
if (t.nodeName == 'SPAN' && t.parentNode.nodeName == 'A') {
t = t.parentNode;
}
DEMO
But why not just get all links in the document, like so:
var links= document.getElementsByTagName("a");
for (var i = 0; i < links.length; i++) {
....
}
This way, you don't need to worry about what kind of tag you've clicked. Here's an example.

JavaScript event handler to insert new pre tag

I have a set of 3 pre tags that are editable. When someone is on one of the lines and hits 'enter', I want it to insert a new tag below (in the document tree) the one it is on. I have tried to put an event handler on the tags so that this occurs, but the 'onkeypress' doesn't seem to be firing.
<script>
function handlers(){
var pres = document.getElementsByTagName("pre");
for(i=0; i<pres.length;i++){
pres[i].addEventListener("onkeypress", function(e){
if(e.which != 13) return;//the ENTER key
var tag = e.srcElement;
if(tag.nextSibling){
var next = tag.nextSibling;
var newPre = document.createElement('pre');
tag.nextSibling = newPre;
newPre.nextSibling = next;
}
var tree = document.getElementById("tree");
tree.innerHTML = document.getElementByTagName().length;
});
}
}
</script>
<body onload="handlers();">
<div id="editor" contentEditable="true">
<pre>1</pre>
<pre>2</pre>
<pre>3</pre>
</div>
<div>
<p id="tree"></p>
</div>
</body>
You are iterating over the array of elements incorrectly, and you are not attaching event listeners correctly.
I recommend changing your for loop to:
for (var i=0, l=pres.length; i<l; i++) {
pres[i];//This is where the Element is stored
}
You can read up on attaching event listeners here
Additionally, it would appear: http://jsfiddle.net/vZYpX that the source of the keypress event under "contentEditable" is the actual element that is "contentEditable". So you have to either make the <pre>s content editable (and not the div), or attach the listener to the parent div (that is currently contentEditable).
I'm not sure the 'onkeypress' can be fired from 'pre' tag.
However I have a suggestion:
1. Register document.onmousemove to detect mouse position.
2. Register document.onkeypress event and when detecting the 'enter' key, check if the mouse is over a 'pre' tag. If so, run your code.
It should look like this:
function moveMoveHandler(e)
{
var evt = window.event || e;
window.lastMouseX = evt.clientX;
window.lastMouseY = evt.clientY;
}
function keypressHandler(e)
{
var evt = window.event || e;
// handling only 'enter' key
if (evt.keyCode !== 13) return;
// getting the element the mouse is on
var elem = document.elementFromPoint(window.lastMouseX,window.lastMouseY);
var node = elem;
// checking if the found node is a child of a 'pre' node
while (node.nodeName !== "PRE" && node !== document.body)
node = node.parentNode;
if (node.nodeName === "PRE")
{
... INSERT YOUR CODE HERE ...
}
}
// IE
if (window.attachEvent)
{
document.attachEvent("onkeypress", keypressHandler);
document.attachEvent("onmousemove", moveMoveHandler);
}
// other browsers
else
{
document.addEventListener("keypress", keypressHandler, false);
document.addEventListener("mousemove", moveMoveHandler, false);
}

Categories

Resources