First a short background. So I just started practicing using API's. With the one I'm working with right now, I'm loading a DIV which have alot of links in it which I have to give a new purpose. I managed to prevent the default onclick-function. Now I need do save the clicked link "innerHTML" attribute.
var nextPage = document.getElementsByTagName("a")[this].innerHTML;
with [this] I tried to target the clicked link, but it didn't work. Hopefully you understands what I'm trying to do. If so, is there any way I an solve this problem?
Thanks!
EDIT:
$("#content, a").click(function(event){
event.preventDefault();
var x = document.getElementsByTagName("a")[0].innerHTML;
console.log(x)
getPage(x);
});
You can add an onclick listener to all the a tags elements
var links = document.getElementsByTagName('a');
for (var i = 0, il = links.length; i < il; i++) {
links[i].onclick = clickHandler;
}
function clickHandler(event) {
console.log(this.innerHTML);
}
<a>Link a</a>
<a>Link b</a>
first the document.getElementsByTagName("a")[this].innerHTML; will return undefined because it will return a collection of html node and it must pass index not the this.
Since you already have a click you can try this code :
function yourClickFunction(event) {
var target = event.target || event.srcElement;
var nextPage = target.innerHTML;
}
Use jQuery for this:
$('a').on('click', function(){
// this will run with every click, and 'this' will be your clicked item
console.log(this.innerHTML);
// although you probably want:
console.log($(this).attr('href'));
});
Using jQuery makes your code much cleaner, and unifying the cross browsers compatibility issues you might have when handling directly with the DOM api.
this.innerHTML can do the work, if I am getting you correctly.
If you are getting the entire html in it, you can bind an onclick event to the anchor itself and can work on that if that is possible.
<a onclick="clicked(this)">Click me</a>
function clicked(element) {
// Do whatever needed
// element.innerHTML will change it's innerHTML
}
You can it like the following too
$("#content, a").click(function(event){
event.preventDefault();
event.target.innerHTML = "Whatever";
})
You could use a common class (link in the below example) to attach the click event then just use this.innerHTML to return the text of you clicked link.
Hope this helps.
var classname = document.getElementsByClassName("link");
var clickFunction = function(){
//Prevent default
if ( event.preventDefault ) event.preventDefault();
event.returnValue = false;
//Get text
console.log(this.innerHTML);
}
for(var i=0;i<classname.length;i++){
classname[i].addEventListener('click', clickFunction, false);
}
<a href='link-1' class='link'>Link 1</a>
<a href='link-2' class='link'>Link 2</a>
<a href='link-3' class='link'>Link 3</a>
document.getElementsByTagName("a") gives you an array of HTMLAnchorElement. The indexes of the array are integer values from 0 to n.
this in your context i think it's the windows object (your code example is a bit short so i have to guess a bit)
using window as the index for the array that expects an integer of course gives you nothing. or undefined to be precise.
There're two possible ways to do what you're looking for:
onclick handler
function hello(elem) {
console.log("you clicked on '" + elem.innerHTML + "'")
}
click me
Here i'm using the onclick property and I pass the this context from the html as an argument to the function i'm calling. This is important.
Now i can operate on the element that was clicked just by referencing the argument received.
I would not suggest this method for a number or reasons. But since you mention the onclick property in the question ...
click event handler
this would be my preferred solution
function hello(evt) {
var elem = event.target || event.srcElement;
console.log("you clicked on '" + elem.innerHTML + "'");
}
var link = document.getElementsByTagName("a")[0]
link.addEventListener("click", hello)
click me
Here there's no code (or reference to the code) in the html. You instead retrieve the HTMLAnchorElement from the code and attach a listener to the click event.
Now the event handler will be called whenever the link is clicked and it will receive an event object by default. From that object you can extract the target (the object that generated the event) and access its properties.
Related
This question already has answers here:
add event listener on elements created dynamically
(8 answers)
Closed 6 years ago.
I am trying to console.log the value of data-number attribute of <span> on click event using JavaScript. Multiple spans are dynamically created during the execution of the code on the client side and each of them have a class "dynamic-span".
Sample:
<span class="dynamic-span" data-number="1">This is a dynamic span</span>
So when the above span is clicked, number "1" will be console logged.
I am able to log the number using jQuery.
$("body").on("click", ".dynamic-span", function (e) {
e.preventDefault();
var number = $(this).data("number");
console.log(number);
});
I want to achieve the same result using plain JavaScript.
I am targeting the span using the "dynamic-span" class.
var elems = document.getElementsByClassName("dynamic-span");
So, I am able to get the spans using the ClassName. But I am getting HTMLCollection and not an Array and the for loop is not working.
Code:
var
elems = document.getElementsByClassName("dynamic-span"),
i;
for (i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", function (e) {
console.log(this.getAttribute("data-number"));
});
}
I have also checked the following StackOverflow question
JavaScript click event listener on class
but no success.
The following reference
https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName
suggests the Element.getElementsByClassName() method returns a live HTMLCollection.
Kindly suggest a way to accomplish the above task.
hopefully this should do it for you:
document.body.onclick = function (e) {
//get event object (window.event for IE compatibility)
e = window.event || e;
//get target dom object reference
var targetDomObject = e.target || e.srcElement;
//extra checks to make sure object exists and contains the class of interest
if ((targetDomObject) && (targetDomObject.classList) && (targetDomObject.classList.contains("dynamic-span"))) {
var number = targetDomObject.getAttribute("data-number");
console.log(number);
}
}
This makes use of bubbling. Whenever an event fires it will move up through all the objects parents until it is marked as handled or there are no more parents. So by attaching to the body's click event it will catch all unhandled click events on the page. The top of the method gets a reference to the event information then it pulls the initial target object from the event. Then all you need to do is see if the object is the object you want to handle and handle it.
Here is a jsfiddle of the code: https://jsfiddle.net/t4jqtLas/
when i use the .preventDefault on a link it still goes to the link - also is this even doable with JS or is it a jquery only method?
var avoidlink = getElementsByTagName("a");
avoidlink.addEventListner("click",function(evt){
evt.preventDefault();
},false);
Click here
Three problems :
getElementsByTagName must be called on the document or on an element
You can't add an event listener directly on the node list returned by getElementsByTagName, you must iterate over the elements it contains :
you have a typo in addEventListener
Here's a fixed code :
var avoidlink = document.getElementsByTagName("a");
for (var i=0; i<avoidlink.length; i++) {
avoidlink[i].addEventListener("click",function(evt){
evt.preventDefault();
},false);
}
If you want to be able to attach an event listener to a node list, you may enrich NodeList.prototype :
NodeList.prototype.addEventListener = function(){
for (var i=0; i<this.length; i++) {
Element.prototype.addEventListener.apply(this[i] , arguments);
}
}
Demonstration
Modifying the prototype of objects you don't own is generally frowned upon but this change is rather innocuous and natural.
Usually if many elements need the same event listener you can add the event listener to the container and filter out what element you would like to take action upon:
document.addEventListener("click",function(e){
if(e.target,e.target.tagName.toLowerCase()==="a"){
e.preventDefault();
}
});
If you were to add extra anchor tags through script they will trigger the preventDefault too.
I've been struggling with what seems to be a simple problem for a few hours now. I've written a REGEX expression that works however I was hoping for a more elegant approach for dealing with the HTML. The string would be passed in to the function, rather than dealing with the content directly in the page. After looking at many examples I feel like I must be doing something wrong. I'm attempting to take a string and clean it of client Events before saving it to our Database, I thought jQuery would be perfect for this.
I Want:
Some random text click here and a link with any event type
//to become:
Some random text click here and a link with any event type
Here's my code
function RemoveEvilScripts(){
var myDiv = $('<div>').html('testing this Do it! out');
//remove all the different types of events
$(myDiv).find('a').unbind();
return $(myDiv).html();
}
My results are, the onClick remains in the anchor tag.
Here's a pure Javascript solution that removes any attribute from any DOM element (and its children) that starts with "on":
function cleanHandlers(el) {
// only do DOM elements
if (!('tagName' in el)) return;
// attributes is a live node map, so don't increment
// the counter when removing the current node
var a = el.attributes;
for (var i = 0; i < a.length; ) {
if (a[i].name.match(/^on/i)) {
el.removeAttribute(a[i].name);
} else {
++i;
}
}
// recursively test the children
var child = el.firstChild;
while (child) {
cleanHandlers(child);
child = child.nextSibling;
}
}
cleanHandlers(document.body);
working demo at http://jsfiddle.net/alnitak/dqV5k/
unbind() doesn't work because you are using inline onclick event handler. If you were binding your click event using jquery/javascript the you can unbind the event using unbind(). To remove any inline events you can just use removeAttr('onclick')
$('a').click(function(){ //<-- bound using script
alert('clicked');
$('a').unbind(); //<-- will unbind all events that aren't inline on all anchors once one link is clicked
});
http://jsfiddle.net/LZgjF/1/
I ended up with this solution, which removes all events on any item.
function RemoveEvilScripts(){
var myDiv = $('<div>').html('testing this Do it! out');
//remove all the different types of events
$(myDiv)
.find('*')
.removeAttr('onload')
.removeAttr('onunload')
.removeAttr('onblur')
.removeAttr('onchange')
.removeAttr('onfocus')
.removeAttr('onreset')
.removeAttr('onselect')
.removeAttr('onsubmit')
.removeAttr('onabort')
.removeAttr('onkeydown')
.removeAttr('onkeypress')
.removeAttr('onkeyup')
.removeAttr('onclick')
.removeAttr('ondblclick')
.removeAttr('onmousedown')
.removeAttr('onmousemove')
.removeAttr('onmouseout')
.removeAttr('onmouseover')
.removeAttr('onmouseup');
return $(myDiv).html();
}
How can I get the href of an anchor when I click on it using JavaScript?
I did the following:
function myFunc() {
}
window.onclick = myFunc;
But how to extend the function to respond only to clicks on anchors and get the href?
function linkClick(e) {
alert(e.target.href);
}
links = document.getElementsByTagName('a');
for (i = 0; i < links.length; i++)
links[i].addEventListener('click', linkClick, false);
Your document.onclick registers the handler on the whole document. But you should add it to every link. You can do this with JavaScript and using a framework like Prototype or jQuery makes it a lot easier:
$$('a').invoke('observe', 'click', function(a){
myFunc(a);
});
But you can also use pure JS combining the getElementsByTagName function with a loop (see Delan's new answer).
it won't work like this, you need to setup an onclick handler for every anchor. The easiest way to do this, is to use a javascript framework like jQuery or Prototype or something similar.
extend your function to recieve the calling object:
var myFunc = function(target) {
var href = target.href;
// ... your function code that can now see the href of the calling anchor
}
jQuery:
$('a').click(function(){
myFunc(this);
});
Protype: see Kau-Boy's answer
function myFunc(link) {
alert(link.href);
return false; // return false if you don't want to actually navigate to that link
}
<a href onclick="return myFunc(link)">something</a>
If I have code like this:
<script>
function determine()
{
// ????
}
</script>
blah1
blah2
Is there a way in determine() to see which link was clicked?
(Yes, I know, the easy and correct thing to do would be to pass this to determine(), but in this case that's not going to be easy to do because of legacy code issues.)
EDIT: I probably should have mentioned this at the beginning...our site is not currently using (and cannot use, for the time being) jQuery, so jQuery answers (while valuable in general for this type of question) won't actually help me.
Check out this link from quirksmode. You can get the event target.
function doSomething(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
}
You can with straight up JavaScript, but I prefer to use something like jQuery:
blah1
<script type="text/javascript">
$('a[href=blah1]').click(function() {
var link = $(this); // here's your link.
return false; // acts like the link was not clicked. return true to carry out the click.
});
</script>
Assuming you are using the $().click() functionality, $(this) will give you the link.
If you cannot change the onclick="determine()" in your HTML, but you can change the determine() function, then I think your best bet is to:
Leave the determine() function blank so it doesn't do anything.
Use javascript (as described by other answers) to add a real click handler to each link, and use the event to determine which link was clicked then execute the desired code.
you could add events to each link like so
links = document.getElementsByTagName('a');
for (link in links) {
link.onclick = function() {
alert(this.id);
determine(); // or some other important code?
}
}
Another solution:
Add an onclick handler to the document. When a user clicks the link, the click event will "bubble" up to the window, and you will have access to the event to determine which link was clicked.
This might be useful if you only want the code to run for those links that already have onclick="determine()" - you could set the determine() function to set a variable. Then when the user clicks the link, the determine() function runs to set the variable, and when the document click handler runs you could check for the variable - then you will know that the link had onclick="determine()".
Let me know if I can make this a little more complicated for you... :-)
If you can't change the onclick attribute, patch it via JavaScript:
// use a DOMContentLoaded hack or `onload` as fallback
onload = function() {
var links = document.links;
for(var i = 0; i < links.length; ++i) {
// there might be a better way to check which links to modify
// don't know without further details
if(/determine\(\)/.test(links[i].onclick))
links[i].onclick = determine;
}
};
function determine() {
// the link is now available as `this`
alert(this.href);
}
Perhaps an even better solution would be to patch in a global, IE-style event object for standards compliant browsers:
if(document.addEventListener) {
document.addEventListener('click', function(e) {
window.event = e;
}, true);
}
function determine() {
var src = event.target || event.srcElement;
alert(src.href);
}