Can I tell anything about a hyperlink that was clicked in JavaScript? - javascript

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);
}

Related

get element by tag name [this]?

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.

Stop click event propagation

I'm trying to highlight any DOM element of a certain Web page when the user clicks on it. For that purpose, I iterate through all elements of the current element and disable any functionality (so e.g. I can click and not to be redirected):
var elems = window.document.getElementsByTagName('*');
for (var i = 0; i < elems.length; i++) {
elems[i].onclick = function(e){
e.preventDefault();
}
The thing is, when user clicks, a lot of click events are fired, because every element has tas behaviour, and I need to avoid unhighlight.
Any idea of how to improve that or any alternative?
Thanks a lot!
P/d: It has to be pure JS
You'll need to do two things: first of all, you want to actually add an event, not redefine its click behaviour, and secondly, uou want it to not bubble up through the dom. Try this:
var elems = window.document.getElementsByTagName('*');
for (var i = 0; i < elems.length; i++) {
// Use addEventListener to listen for events.
// Older version of IE use attachEvent, but I guess thats irrelevant.
elems[i].addEventListener("click", function(e){
e.preventDefault();
// Use stopImmediatePropagation to stop the element from passing this click to wrapping parents - because a click on a child is technically a click on the parent as well.
e.stopImmediatePropagation();
});
}
Heres more to read:
Add Event Listener: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
Stop Immediate Propagation: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation
As a brave editor says, you can also pass false as a third argument to the addEventListener and it does basically the same thing but is less comprehensible and does some additional things as well, so I have opted not to default to this just because its easier to understand that you are stopping propagation.
I made a jsfiddle that does it:
https://jsfiddle.net/zgqpnaey/
var elems = window.document.getElementsByTagName('*');
for (var i = 0; i < elems.length; i++) {
myFunction(elems[i]);
}
function myFunction(element) {
element.onclick = function(e) {
e.preventDefault();
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
element.style.background = 'red';
};
}
somethinghere explained it above.
Also, you shouldn't bind onclick inside a loop, it's known to cause errors; it's better to call a function and pass the proper parameters.

How to perform some action when a user touches anywhere that isn't a link/anchor etc?

I'm using html/javascript with iOS and UIWebView.
I want to invoke an objective-c method when the user touch anywhere on the page that isn't a link.
At the moment I have
...
<BODY ontouchend="bodyTouch();">
<HEAD>
<script language="javascript" type="text/javascript">
function bodyTouch() {
invokeObjectiveC();
}
}
</script>
...
<DIV id=buttons>
<A id=navigator href="CustomScheme:SomeAction"></A>
....
How can I set things up so that bodyTouch() only gets invoked if the user touches anywhere on the screen that isn't a link/button/anchor etc.
==== Update ===
Thanks for lots of answers folks.
Unfortunatly I couldn't get any of them to work (now my InvokeObjectiveC() doesn't get called at all when I try any of them).
I'm an iOS developer and don't know html/javascript. I'll do a bit of studying as I don't understand any of the answers at the moment with my limited knowledge, then try them once I understand what they are doing and try to figure out why its not working.
I'll mark one of the answers as accepted in due course.
Cheers
document.body.addEventListener('click', function(event){
bodyClick();
}, false);
document.querySelector('a').addEventListener('click', function(event){
event.stopPropagation();
}, false);
​
Learn more about stopPropagation at Mozilla Developer Network
JSFiddle
give this one a shot, you should be able to place this anywhere in the document
<script>
document.addEventListener('DOMContentLoaded', function () {
document.documentElement.addEventListener('click', function (e) {
/* CHECK IF THE TARGET IS IN YOUR BANLIST */
if (['A', 'BUTTON'].indexOf(e.target.tagName) === -1) {
/* I WOULD CALL THESE FOR GOOD MEASURE */
e.preventDefault();
e.stopPropagation();
/* THIS IS YOUR FUNCTION */
invokeObjectiveC();
}
}, true);
}, false);
</script>
this does not work on the input[type=button] looking buttons, if you need that as well let me know
using jQuery delegate and selector,
but be careful if the original element trigger that event uses stopPropagation
Similar to Roderick's response, but a bit more cross-browser friendly
document.getElementsByTagName('html')[0].addEventListener('click', function (ev) {
var el, elN;
ev = ev || window.event;
el = ev.target || ev.srcElement;
elN = el.nodeName.toLowerCase();
if (elN == 'a' || elN == 'input') return false;
invokeObjectiveC();
}, true);

buttons with no href, onclick etc

Lately, I've been seeing a lot of sites that have clickable objects that don't have any hrefs or onclicks in their html code. I also tried alerting their href, onclick, onmousedown, onmouseup attributes but it only says "undefined". I do notice that there's a lot of complicated javascript in these pages.
one site in particular baffles me:
http://www.sharenator.com/Boy_Teaches_His_Puppy_How_to_Eat/#/doggy_01_Boy_Teaches_His_Puppy_How_to_Eat-0.html
It's actually pretty good. The buttons aren't selectable as well. The ids of the buttons are nextBtn, nextBtn2, prevBtn and prevBtn2.
Anybody has any idea how to implement this?
You can use jQuery's .click(callback) function (http://api.jquery.com/click/) or .delegate(selector, 'click', callback) (prior to jQuery 1.7) and .on('click', selector, callback) (jQuery 1.7+) or .bind('click', callback).
Thanks to Anthony Grist for pointing out that .live() is now deprecated :)
As so:
<button id="clickable">Click Me!!</button>
Then target the button with jQuery:
$("#clickable").click(function(){
// Send user to this link
location.href = "http://www.takemehere.com";
});
You can read more about this on the link I gave, and on jQuery's homepage.
UPDATE
The actual page handles this with:
$('#prevBtn').mousedown (onBackward);
Which would onmousedown call:
function onBackward () {
showImg (currentId - 1);
}
The use of arrow keys:
$(document).keyup (function (event) {
var activeElement = document.activeElement.tagName;
if (activeElement == 'INPUT' || activeElement == 'TEXTAREA') return;
//alert (window.location.pathname);
if (event.keyCode == 39) onForward();
else
if (event.keyCode == 37) onBackward();
});
See http://www.sharenator.com/js/slideshow.js for the source code of the slideshow.
You could try using the jQuery ui library - this can create buttons in the way you specify.
jQuery UI
The event handlers are probably bound using a Javascript framework such as jQuery. They don't use the onclick property of the DOM element. See this jsFiddle for an example of binding a click event handler to a button with jQuery, then click the button to see the value of onclick for that button (displays as null in FF 9).
With javascript, find the element and give it an onClick event handler. e.g.:
var myElement = document.body; // or document.getElementById(...), etc.
myElement.onclick = function(event) {alert(event);}
This will avoid showing anything in the HTML, and is how the website you linked does it (there is no other way to define behavior... except maybe esoteric CSS).
With javascript. Here's an example:
<a id="uniqueId" href="#">Button</a>
<script>
var button = document.getElementById('uniqueId');
button.onclick = function(e) {
alert("clicked!");
}
</script>
the click functions may be initialized in js, for example, $("#nextBtn").click(function);

JavaScript get anchor href on click

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>

Categories