click() does not work with links

Go To StackoverFlow.com

3

I have a page with a few links that are all like this:

<a href="/" class="answer-item" rel="0">10</a>

I would like to use the click() function to simulate a user's click on one of them, but it doesn't seem to work in my tests.

//Evaluate a mathematical expression from another part of the page
var numberAnswer = eval(document.getElementById("question-title").getElementsByTagName("b")[0].innerHTML);

//Builds an array with the links that may match the expression
var choices = document.getElementsByClassName('answer-item');

//Iterates through array to find a match then clicks it
for(var i in choices){
    if(choices[i].innerHTML == numberAnswer){
        choices[i].click();
        break;
    }
}

I'm sure that choices[i] is the correct element.

Firefox does nothing, Opera does nothing, and click() is not available in Chrome (I think).

Also, I have tried to use dispatchEvent() in this form:

var evt = document.createEvent('MouseEvents');
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
choices[i].dispatchEvent(evt);

This apparently returned true in Firefox and Chrome but did not change anything.

The most bothersome part is that a link with only the href attribute works fine with .click().

2012-04-03 20:25
by MarkM


3

EDIT

Per discussion in the comment area, it seems that the behavior used in this answer is non-standard, or at least not consistent across user-agents. I am researching this issue further; if you use the information in this answer, please carefully check your code in all browsers to ensure it works as expected.


EDIT 2

Per the comment from the OP, there is a "just make it happen" approach that would work here. It has some downsides, namely that your bound events cannot call preventDefault -- this method will not respect it. You could build some kind of event wrapper that might be able to deal with this... anyway, here's the code and fiddle:

HTML:

<br><br>
<!-- I am totally misusing this API! -->
<a href="http://jsfiddle.net/echo/js/?delay=0&js=The link was followed;" id="progra_link">Some link with an event that uses preventDefault()</a>
<br><br>
<button id="doit_btn">Programmatically click the link</button>

Script:

function do_program_click () {
    var lnk = document.getElementById('progra_link');
    var loc = lnk.href;
    if (!loc)
        return false;            
    // call this to fire events
    lnk.click();

    // then follow the link
    document.location = loc;
    return;
};
function addEvent(element, evnt, funct){
  if (element.attachEvent)
   return element.attachEvent('on'+evnt, funct);
  else
   return element.addEventListener(evnt, funct, false);
}

// bind an event to the link to test force event trigger
addEvent(
    document.getElementById('progra_link'),
    'click',
    function (e) {
        e.preventDefault();
        alert('Testing element click event, default action should have been stopped');
        return false;
    }
);
// bind event to the leeroy button
addEvent(
    document.getElementById('doit_btn'),
    'click',
    do_program_click
);

jsFiddle: http://jsfiddle.net/CHMLh/


Original answer

Your sample code is incomplete. If I take just the basics, it works correctly:

<script>
   var lnk = document.getElementById('test');
   lnk.click();
</script>
<a id="test" href="/" class="answer-item" rel="0">test link</a>

jsFiddle: http://jsfiddle.net/cgejS/

I would re-evaluate your assumptions that you're dealing with the correct dom element.

On an unrelated note, this:

var numberAnswer = eval(document.getElementById("question-title").getElementsByTagName("b")[0].innerHTML);

... what? eval is evil -- if you're ever using it for any reason, question whether you have the right approach. Are you trying to get an integer out of a string? See parseInt (docs), the right tool for this job:

// this line is still failure-prone...
var ele = document.getElementById("question-title").getElementsByTagName("b")[0];
var numberAnswer = 0;
if (ele)
   numberAnswer = parseInt(ele.innerHTML);
2012-04-03 20:35
by Chris Baker
Not sure what browser you are using, but under Chrome your code does nothing (even with something other than / as the URL - Chris Laplante 2012-04-03 20:40
The jsFiddle I posted, in Firefox, navigates the results pane to jsFiddle's home page -- it follows the / url as expected. Will test in Chrome and update here - Chris Baker 2012-04-03 20:41
Confirm - this does not work in Chrome. Will edit, thanks for the info - Chris Baker 2012-04-03 20:42
Not a problem. I've revoked my downvote in anticipation of your edit - Chris Laplante 2012-04-03 20:43
Ok, it seems that this works on every browser except Chrome. That's the fault of Chrome, not of your code. I found several articles that cited this fact. So, +1 : - Chris Laplante 2012-04-03 20:47
Heh, do you have some of those articles? Funny thing is... I am finding it hard to justify why it DOES work in Firefox, by all indications it should not. http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-2651361 tells me that only a form submit button should respond with the default browser action upon calling click(). I was starting to think this was non-conforming behavior or even a bug... but if you say everyone else is doing it EXCEPT Chrome, that raises a whole new question! Guess who is going to be posting on wc3\public-html about this tonight : - Chris Baker 2012-04-03 20:51
While I agree that eval is evil, I think it works well in this context because it is evaluating a mathematical expression - MarkM 2012-04-03 20:59
Ah, fair enough. If you're [eval]uating mathematical expressions, then that's one of the rare instances where eval is the tool for the job. I would still question whether it is faster and more secure to determine the answer on the server-side, but you know your use case better than I. :) I am still researching the question of whether click() should work or not, I am not finding any conclusive evidence that it should. Thus, my answer here is not looking like the best approach - Chris Baker 2012-04-03 21:10
I just Googled for it. Here's one "article": http://unitstep.net/blog/2010/04/12/triggering-links-from-javascript-using-jquery/ (according to it, no browsers support it but as you've discovered, some actually do - Chris Laplante 2012-04-04 14:36
From the discussion, it seems that the answer is "click() will not work for this". I'm sure there is a different way of doing this, even if will require more effort. In the meantime, this is the answer - MarkM 2012-04-04 19:24
Check out the second edit, @MarkM - http://jsfiddle.net/CHMLh/ has a solution that does the job... dirt - Chris Baker 2012-04-04 22:00
@Chris Oh my, that is quite ugly (no offence to your excellent coding skills, of course). Fortunately, I have been able to solve my problem through a completely unrelated method that allowed me to avoid having to "simulate a click" at all. Even so, I thank you for the consistent help - MarkM 2012-04-05 01:22


0

Easy.

The HTML (note that I added an 'id' tag):

<a id="answer-item" href="/" class="answer-item" rel="0">10</a>

The JS:

document.getElementById('answer-item').click();
2012-04-03 20:39
by mukama
Note: This doesn't work on Chrome, but that's a limitation of the browser itsel - Chris Laplante 2012-04-03 20:49
Adding an id and using getElementById() did not work, but can you explain why it would? My code already gets the proper element - MarkM 2012-04-03 20:57
It isn't "easy" -- the issue is more complex. Please see the comment discussion on my answer for more info. Basically, it is my finding that click() should NOT work in this instance, the fact that it does is non-standard and/or a bug - Chris Baker 2012-04-03 21:13
In addition, since the OP is calculating a value and then iterating links to find the matching value, using getElementById is a non-starter without going back to a server-side solution that could create unique matching id values that would be used like document.getElementById('answernumber'+numberAnswer)Stephen P 2012-04-04 00:51
Ads