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()
.
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);
/
url as expected. Will test in Chrome and update here - Chris Baker 2012-04-03 20:41
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
eval
is evil, I think it works well in this context because it is evaluating a mathematical expression - MarkM 2012-04-03 20:59
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
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();
getElementById()
did not work, but can you explain why it would? My code already gets the proper element - MarkM 2012-04-03 20:57
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
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
/
as the URL - Chris Laplante 2012-04-03 20:40