Might be a very simple javascript injection question, but say I have an image html tag:
<img src="rainbow.gif">
I wanted to perform a javascript, such that when clicked on the image, it doesn't go to the myfile.htm. In other words, I wanted to strip the a href which surrounds the img. How can I do this in javascript? Say that I have the following to reference the image tag:
document.elementFromPoint(%f, %f)
f can be replaced by any double/float value
If you have a reference to the img element, then its parent (parentNode) will be the link (in the structure you've given). Three options:
Remove the link entirely
Disable the link
Change the link's href
1. Remove the link entirely
You can remove the link entirely by doing this:
var link = img.parentNode,
linkParent = link.parentNode;
linkParent.insertBefore(img, link);
linkParent.removeChild(link);
That uses parentNode to find the parent and grandparent, insertBefore to move the image, and removeChild to remove the link. Note that this assumes the image is the only thing in the link.
2. Disable the link
If you want to keep the link but render it useless, you can do this:
var link = img.parentNode;
if (link.addEventListener) {
link.addEventListener("click", function(event) {
event.preventDefault();
}, false);
}
else if (link.attachEvent) {
link.attachEvent("onclick", function() {
return false;
});
}
else {
link.onclick = function() {
return false;
}
}
3. Change the href of the link:
This is trivial, just set the href property of the link element (which you can get because it's the parent node of the image) to whatever you want:
img.parentNode.href = /* ...something else */;
For instance:
img.parentNode.href = "http://stackoverflow.com";
...would change the link to point to Stack Overflow.
Live example
Some references:
DOM2 Core
DOM2 HTML
DOM3 Core
HTML5 Web Application APIs
<a id="anchorWithImage" href="myfile.htm"><img src="rainbow.gif"></a>
Why not grab the anchor, then set its href to nothing:
var a = document.getElementById("anchorWithImage");
a.href = "javascript:void(0)";
Or grab it and set its click event to cancel the default action, which is to browse to the location of its href property
a.onclick = function(e) {
e.preventDefault();
}
Or do you want to grab all anchors that have an image as their child element, and strip out their href?
jQuery would make this easy, if that's an option for you
$("a").filter(function() {
return $(this).children("a").length === 1;
}).attr("href", "javascript:void(0)");
or
$("a").filter(function() {
return $(this).children("a").length === 1;
}).click(function() { return false; }); //returning false from jQuery handlers
//prevents the default action
EDIT
If you were to have a reference to the image, and wanted to set its parent's anchor's href, you'd grab it with the parentNode property:
var img = document.getElementById("imgId");
var a = img.parentNode;
a.href = "javascript:void(0)";
With jQuery you could use something similar to this
$("a").has("img").click(function(e).preventDefaults();});
Basically all this line does is identifies all tags within the document containing an tag disables standard event process
From your comment on another answer, it sounds like you actually want to change/eliminate the target of links at a specific position in the page. You could do something like this:
var el = document.elementFromPoint(10, 10);
while(el) {
if(el.nodeName.toLowerCase() == 'a')
el.href = 'javascript:';
el = el.parentElement;
}
This would loop up from the selected element, identify if the element is an anchor, and set the href to something that does nothing.
you can change the href of a tag on window load itself, so you need not worry when it is clicked.
window.onload = fundtion(){
var imgs = document.getElementsByTagName('img');
for(var i=0;i<imgs.length;i++){
var parentElem = imgs[i].parentNode;
if(parentElem.tagName === 'A')
parentElem.setAttribute("href", "javascript:void(0)");
}
};
Related
I have a link:
<a href="https://somelink.com" target="_blank">
SOMENAME <i class="fa fa-chevron-right"></i>
</a>
Now, I want to execute javascript whenever the above hyperlink is pressed, without adding any code inside <a href ... /a>.
Is this possible?
Edit:
This question is different from questions asked earlier because I don't have any <id> inside <a href ... /a>.
Also, I cannot add code inline inside <a href ... /a>. I somehow need to track the press of hyperlink, and then execute javascript. Also, I have many such hyperlinks and I need to track them differently.
Either inline:
link
<script type="text/javascript">
function myFunction () {
// return false => does not navigate to href
// return true => navigate to href
}
</script>
Or add click listener via JS:
var link = document.querySelector('a');
link.onclick = function() {
}
EDIT: In case of multiple links:
var links = document.querySelectorAll('a');
for(var i = 0; i < links.length; i++) {
var link = links[i];
link.onclick = function() {
}
}
EDIT2: If you want to discriminate by the href attribute content:
a[href] an a element with a "href" attribute (CSS 2)
a[href="bar"] an a element whose "href" attribute value is exactly equal to "bar" (CSS 2)
a[href~="bar"] an a element whose "href" attribute value is a list of whitespace-separated values, one of which is exactly equal to "bar" (CSS 2)
a[href^="bar"] an a element whose "href" attribute value begins exactly with the string "bar" (CSS 3)
a[href$="bar"] an a element whose "href" attribute value ends exactly with the string "bar" (CSS 3)
a[href*="bar"] an a element whose "href" attribute value contains the substring "bar" (CSS 3)
a[href|="en"] an a element whose "href" attribute has a hyphen-separated list of values beginning (from the left) with "en" (CSS 2)
So you would have:
var link = document.querySelector('a[href="theValueIamLookingFor"]');
link.onclick = function() {
}
EDIT3: You could also test the href values within the for loop:
var links = document.querySelectorAll('a');
for(var i = 0; i < links.length; i++) {
var link = links[i];
link.onclick = function() {
switch(link.href) {
case 'www.google.com':
// Do something
break;
case 'https://stackoverflow.com':
// Do something else
break;
default:
return true;
}
}
}
As you said in your comment that you may have multiple tags in your document the simplest method is to select an element with a particular href.
$('a[href^="https://somelink.com"]').click(function() {
alert('you pressed me');
});
you do not need to edit or add something to your 'a' tag.
If you know the value that is passed in the href attribute, you could do something like :
EDIT
$( "a" ).each(function(){
if($(this).attr("href") === "https://google.com" )
console.log('hey');
});
I'm trying to replace multiple links but only the first one is replaced,
all the other remain the same.
function rep(){
var text = document.querySelector(".link").querySelector("a").href;
var newText = text.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
document.querySelector(".link").querySelector("a").href = newText;
}
Any suggestions?
It's multiple a href links inside .link elements which I'm talking about.
Your mistake is in using querySelector, so document.querySelector(".link").querySelector("a") literally translates to: get me the first a inside the first .link;
Use querySelectorAll; and you can combine the two selectors:
Vanilla JS:
[].forEach.call(document.querySelectorAll('.link a'), function(a){
a.href = a.href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
});
Or, since you'll select items more often, a little utility:
function $$(selector, ctx){
return Array.from((ctx && typeof ctx === "object" ? ctx: document).querySelectorAll(selector));
}
$$('.link a').forEach(function(a){
a.href = a.href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
})
Or in jQuery:
$('.link a').each(function(){
this.href = this.href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/, 'http://google$2com');
});
This doesn't use JQuery, and I've changed your regular expression to something that made more sense for the example. It also works when you run the snippet.
function rep() {
var anchors = document.querySelectorAll(".link a");
for (var j = 0; j < anchors.length; ++j) {
var anchor = anchors[j];
anchor.href = anchor.href.replace(/http:\/\/test(.*)com/, 'http://google$1com');
}
}
rep();
a[href]:after {
content: " (" attr(href)")"
}
<div class="link">
What kind of link is this?
<br/>
And what kind of link is this?
<br/>
</div>
<div class="link">
What kind of link is this?
<br/>
And what kind of link is this?
<br/>
</div>
Edit: Expanded example showing multiple anchor hrefs replaced inside multiple link classed objects.
Edit2: Thomas example is a more advanced example, and is more technically correct in using querySelectorAll(".link a"); it will grab anchors in descendants, not just children. Edited mine to follow suite.
If you intend to only select direct children of link class elements, use ".link>a" instead of ".link a" for the selector.
Try using a foreach loop for every ".link" element. It seems that
every ".link" element have at least 1 anchor inside, maybe just one.
Supposing every .link element has 1 anchor just inside, something like
this should do:
$('.link').each(function(){
// take the A element of the current ".link" element iterated
var anchor = $(this).find('a');
// take the current href attribute of the anchor
var the_anchor_href = anchor.attr('href');
// replace that text and achieve the new href (just copied your part)
var new_href = the_anchor_href.replace(/http:\/\/test(.*)http:\/\/main(.*)com/,'http://google$2com');
// set the new href attribute to the anchor
anchor.attr('href', new_href);
});
I did't test it but it should move you to the way. Consider that we
could resume this in 3 lines.
Cheers
EDIT
I give the last try, looking at your DOM of the updated question and using plain javascript (not tested):
var links = document.getElementsByClassName('link');
var anchors = [];
for (var li in links) {
anchors = li.getElementsByTagName('A');
for(var a in anchors){
a.href = a.href.replace(/http:\/\/test(.*)com/, 'http://google$1com');
}
}
I suggest to read the following post comment for some cooler methods of looping/making stuff foreach item.
How to change the href for a hyperlink using jQuery
So I ran up onto a problem, how would I add text into the HTML attachment href. So, and example:
...
How would I change it too:
...
But, what if I had mutiple of these with different href's:
...
...
...
How would I change them all?
href is called an attribute, and you can use .attr() to change it
If you want to add same prefix to all of them then
jQuery(function () {
$('a').attr('href', function (i, href) {
return 'http://google.com' + href;
});
})
Demo: Fiddle
First find all the elements you wish to change and put them into an array (below, I'm just using all anchor tags, but you could do getElementsByClassName and give them all some class as to not affect every anchor tag on the page), then loop through them and append the code.
(function () {
var anchors = document.getElementsByTagName("a");
for (var x = 0; x < anchors.length; x++) {
anchors[x].href = "http://google.com" + anchors[x].href;
}
})();
If you're appending the same string to the start of all anchor tags' HREF attribute within a particular DIV or other container (say it has ID myDiv), that's relatively easy:
$('#myDiv a').each(function(){
$(this).attr('href', 'http://google.com' + $(this).attr('href'));
});
I am trying to append a link ("a" tag) to a child of the "topBar" element.
Here is what i've got so far:
document.getElementById('topBar').innerHTML += 'Cookie Clicker Classic';
This puts the link inside the "topBar" element as a new child, but I want it inside the existing child of the "topBar" element. How do I do this? The child is just within a div tag, it has no id... I have done some reasearch on .appendChild but I haven't found any related help, thus why I am asking here...
I would be very appreciative for any ideas or even a solution to be posted.
Thanks,
Daniel
EDIT: topBar has only one child, it is nameless
also, am I doing something wrong with this?
setTimeout(doSomething, 1000);
function doSomething() {
var element = document.getElementById('particles');
if (typeof(element) != 'undefined' && element != null)
{
var newLink = document.createElement('a');
newLink.setAttribute('href', 'http://orteil.dashnet.org/experiments/cookie/');
newLink.target = 'blank';
document.getElementById('topBar').appendChild(newLink);
var del = document.getElementById('links')
del.parentNode.removeChild(del);
return;
} else {
setTimeout(doSomething, 1000);
}
}
EDIT: I have finished! Thanks to everyone for their help, especially Elias Van Ootegem. This is what I used:
var link=document.createElement('a');
link.setAttribute('href', 'http://orteil.dashnet.org/experiments/cookie/');
link.target = 'blank';
link.appendChild(
document.createTextNode('Cookie Clicker Classic')
);
var add = document.getElementsByTagName('div')[1]; //this picked the second div tag in the whole document
if(add.lastChild) add.insertBefore(link,add.lastChild); //appending it to the end of the child
else add.prependChild(link);
First, create the node:
var newLink = document.createElement('a');
//set attributes
newLink.setAttribute('href', 'http://orteil.dashnet.org/experiments/cookie/');
newLink.target = 'blank';//preferred way is using setAttribute, though
//add inner text to link:
newLink.appendChild(
document.createTextNode('Cookie Clicker Classic')//standard way, not innerHTML
);
Then, append the child, using appendChild:
document.getElementById('topBar').appendChild(newLink);
Or, given your update (your deleting some other element), use replaceChild:
document.getElementById('topBar').replaceChild(
newLink,//new
document.getElementById('links')//old, will be removed
);
And you're there!
I have a list of href / text that I need to make anchors for and then display those anchors. Everything is fine until I actually click any of the anchors. They each only open a tab for the last href. I.e. if the href of the last element in the list is href_n, then every anchor links to href_n, even if the 'href' attribute is different.
//Current basic setup:
loop through list:
anchor = doc.create('a')
divElem = doc.create('div')
anchor.setAttribute('class', 'foo')
anchor.setAttribute('href', 'bar')
anchor.innerHTML = 'mytext'
anchor.addEventListener('click', function() {chrome.tabs.create({url: 'myurl'})});
divElem.appendChild(anchor)
container.appendChild(anchor)
Previously I tried using .onClick, but I kept having a problem with the event listener trying to just attach to the url. I am very amenable to a cleaner solution though that involves something simpler than an eventlistener.
Thanks much.
You mostly just need to change your click handler to not use variables that are not still valid. Here's sample code:
var urlList = [
"aaaa",
"bbbb",
];
var textList = [
"text1",
"text2"
];
function createAnchors(urls, text, container) {
for (var i = 0; i < urls.length; i++) {
var a = document.createElement("a");
var div = document.createElement("div");
a.href = urls[i];
a.innerHTML = text[i];
a.className = "foo";
a.addEventListener("click", function() {
chrome.tabs.create({url: this.href});
return(false);
});
div.appendChild(a);
container.appendChild(div);
}
}
The issue is that any variables in your event listener function are not evaluated until the click. So, in this case, you can avoid using them by just getting the url directly from the clicked link.
I hope you also realize that older versions of IE don't support addEventListener. This mozilla page shows you how you can handle that in the Internet Explorer section.
You need to create a closure:
var urls = [];
for(var i=0;i<urls.length;i++){
anchor.addEventListener('click',
(function(url) {
return function() {
chrome.tabs.create({url: url})
}
})(urls[i])
);
}