Simulating a click in jQuery/JavaScript on a link - javascript

I want to simulate a click on any link on a page using JavaScript. If that link has some function binded to its 'onclick' event (by any other JS I don't have any control over), then that function must be called otherwise the link should behave in the normal manner and open a new page.
I am not sure that just checking the value of the 'onclick' handler would suffice. I want to build this so that it works on any link element.
I have no control over what function maybe binded to the onclick event of the link using whichever JS library (not necessarily jQuery) or by simply using JavaScript.
EDIT: With the help of the answers below, it looks like it is possible to check for event handlers attached using jQuery or using the onclick attribute. How do I check for event handlers attached using addEventListener / any other JS library so that it is foolproof?

You can use the the click function to trigger the click event on the selected element.
Example:
$( 'selector for your link' ).click ();
You can learn about various selectors in jQuery's documentation.
EDIT: like the commenters below have said; this only works on events attached with jQuery, inline or in the style of "element.onclick". It does not work with addEventListener, and it will not follow the link if no event handlers are defined.
You could solve this with something like this:
var linkEl = $( 'link selector' );
if ( linkEl.attr ( 'onclick' ) === undefined ) {
document.location = linkEl.attr ( 'href' );
} else {
linkEl.click ();
}
Don't know about addEventListener though.

Why not just the good ol' javascript?
$('#element')[0].click()

Just
$("#your_item").trigger("click");
using .trigger() you can simulate many type of events, just passing it as the parameter.

Easy! Just use jQuery's click function:
$("#theElement").click();

Try this
function submitRequest(buttonId) {
if (document.getElementById(buttonId) == null
|| document.getElementById(buttonId) == undefined) {
return;
}
if (document.getElementById(buttonId).dispatchEvent) {
var e = document.createEvent("MouseEvents");
e.initEvent("click", true, true);
document.getElementById(buttonId).dispatchEvent(e);
} else {
document.getElementById(buttonId).click();
}
}
and you can use it like
submitRequest("target-element-id");

At first see this question to see how you can find if a link has a jQuery handler assigned to it.
Next use:
$("a").attr("onclick")
to see if there is a javascript event assigned to it.
If any of the above is true, then call the click method. If not, get the link:
$("a").attr("href")
and follow it.
I am afraid I don't know what to do if addEventListener is used to add an event handler. If you are in charge of the full page source, use only jQuery event handlers.

All this might not help say when you use rails remote form button to simulate click to. I tried to port nice event simulation from prototype here: my snippets. Just did it and it works for me.

Related

Get elements by event listener

Is there a way to get all elements that have a certain event listener attached to them?
I know I can get them if the event listener is defined as an attribute:
var allElemsInBodyWithOnclickAttr = $("body").find("*[onclick]");
But I have elements that have event listeners that are attached by code and thus have no onclick attribute.
So when I do (for example) this:
$("a").on("click", function(evt) {
alert("Hello");
});
..then using the code below doesn't fire the click on those anchor elements:
$("a[onclick]").trigger("click");
I guess I could loop through all the elements and check if they have the listener I'm looking for (using this SO question) but I can't imagine that's going to perform very well..
Can't add comments, but still - consider using https://github.com/ftlabs/fastclick for removing the delay.
That helped me, when i was developing app using cordova.
Also, didn't notice you have already mentioned this post, so i have written implementation for 'loop through all elements'-type-of-solution
Array.prototype.reduce.call(
$('body').children(),
(answer, node) => {
if (typeof $._data($(node)[0], 'events') != 'undefined') {
answer.push(node);
}
return answer;
},
[]
);
I think this is not possible, since it is not possible to test if a single element has an event listener attached to it.
Look here
So the only way to do that is to manage a map which contains a reference to each event handler for each event for each element.
Edit
With respect to the answer of #Ivan Shmidt, I must correct my answer: Obviously It seams to be possible with jQuery. That is because jQuery is holding a reference of attached event handlers, BUT events attached using good old .addEventListener() would bypass this and also not be found this way.

Calling an Onclick() function without clicking?

A websites Button isn't rendering on my browser. I know it's there, when I'm in the view source I still see the button, and the onclick function. Can I still call this function by passing the url the function? Or in the console?
Even if it's not an onclick, is it possible to call functions by either URL or Console?
You can click any DOM element by selecting it and calling the click() function.
document.getElementById("yourElementId").click();
Works with Jquery as well.
$(selector).click();
To accomplish this, you can use the following line:
document.getElementById("element_id").click()
According to MDN, this simulates a full click on the element, including all it entails:
When click is used with elements that support it (e.g. one of the types listed above), it also fires the element's click event which will bubble up to elements higher up the document tree (or event chain) and fire their click events too. However, bubbling of a click event will not cause an element to initiate navigation as if a real mouse-click had been received.
Alternatively, you can use jQuery to accomplish the same thing:
$("#trigger").click();
Here is the simplest way:
function fireClick(node){
if ( document.createEvent ) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if( document.createEventObject ) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function' ) {
node.onclick();
}
}
So you can trigger the click event for an element like below:
fireClick(document.getElementById('id'));
Reference from here.

Manually click a child link (and navigate) when clicking parent [duplicate]

Recently I found jQuery cannot trigger the native click event on an anchor tag when I'm clicking on other elements, the example below won't work:
html
<a class="js-a1" href="new.html" target="_blank">this is a link</a>
<a class="js-a2" href="another.html" target="_blank">this is another link</a>
javascript
$('.js-a1').click(function () {
$('.js-a2').click();
return false;
});
And here is the jsfiddle - 1. Click on the first link won't trigger native click on the second one.
After some searches, I found a solution and an explanation.
Solution
Use the native DOM element.
$('.js-a1').click(function () {
$('.js-a2').get(0).click();
return false;
});
And here is the jsfiddle - 2.
Explanation
I found a post on Learn jQuery: Triggering Event Handlers. It told me:
The .trigger() function cannot be used to mimic native browser events, such as clicking on a file input box or an anchor tag. This is because, there is no event handler attached using jQuery's event system that corresponds to these events.
Question
So here comes my question:
How to understand 'there is no event handler attached using jQuery's event system that corresponds to these events'?
Why is there not such corresponding event handler?
EDIT
I update my jsfiddles, it seems there's and error on the class name.
there is no event handler attached using jQuery's event system that corresponds to these events
This means, at this point of the learning material, no jQuery event handlers has been attached to these elements using .click(function() {} or .bind('click', function () {}), etc.
The no-argument .click() is used to trigger (.trigger('click')) a "click" event from jQuery's perspective, which will execute all "click" event handlers registered by jQuery using .click, .bind, .on, etc. This pseudo event won't be sent to the browser.
.trigger()
Execute all handlers and behaviors attached to the matched elements for the given event type.
Check the updated jsFiddle example, click on the two links to see the difference. Hope it helps.
First of all you need to prevent the default behaviour of link
$('.js-a1').click(function (e) {
e.preventDefault();
$('.js-a2').get(0).click();
return false;
});
And to trigger the click event you can also use .trigger('click') better way
And the event handler is used like this:
$(document).on('click', '.js-a1',function(){//code in here});
// here now .js-a1 is event handler
i think you forgot to read documentation.
Document says :
// Triggering a native browser event using the simulate plugin
$( ".js-a2" ).simulate( "click" );
Old question, but here's a nifty and simple solution:
You can basically "register" a native JS event with jQuery by assigning the DOM element's onEvent handler to be the native event. Ideally, we would check first to ensure the onEvent handler has not already been set.
For example, 'register' the native JS click event so it will be triggered by jQuery:
$('.js-a1').click(function (e) {
$('.js-a2').click();
e.preventDefault();
});
var trigger_element = $('.js-a2')[0]; // native DOM element
if (!trigger_element.onclick) {
trigger_element.onclick = trigger_element.click;
}
Here is a fiddle: http://jsfiddle.net/f9vkd/162/
You have to use $("selector").trigger('click')

Jquery remove and add back click event

Is it possible to remove than add back click event to specific element? i.e
I have a $("#elem").click(function{//some behaviour});, $(".elem").click(function{//some behaviour});(there are more than 1 element) while my other function getJson is executing I'd like to remove the click event from the #elem, and add it again onsuccess from getJson function, but preserve both mouseenter and mouseleave events the whole time?
Or maybe create overlay to prevent clicking like in modal windows? is that better idea?
edit :
I've seen some really good answers, but there is one detail that I omitted not on purpose. There are more than one element, and I call the click function on the className not on elementId as I stated in the original question
Rather than using unbind(), which means you'll have to rebind the same event handler later, you can use jQuery's data() facility with the ajaxStart and ajaxStop events to have your elements ignore click events during all AJAX requests:
$(".elem").click(function() {
if (!$(this).data("ajaxRequestPending")) {
// some behaviour
}
}).ajaxStart(function() {
$(this).data("ajaxRequestPending", true);
}).ajaxStop(function() {
$(this).removeData("ajaxRequestPending");
});
EDIT: This answer is also id-to-class-proof (see questioner's edit), since everything matching the selector will handle the AJAX events the right way. That's the main selling point of jQuery, and it shows.
You are looking for .unbind(). Pass it 'click' and it will destroy the click event.
I would put it just before your getJSON and re-bind the click event inside the success handler of your ajax call.
You have to do some additional scripting. There is no callback for that. Take a look over here: jQuery - How can I temporarily disable the onclick event listener after the event has been fired?
Rather than unbinding/binding the click event, you could check the state of another variable to see if it should do the action.
var MyObject = {
requestActive = false;
};
function MyJsonFunction() {
// when requesting
MyObject.requestActive = true;
//...
// when request over
MyObject.requestActive = false;
}
$("#elem").click(function{
if (MyObject.requestActive == true) {
//do something
}
});

Can I call jQuery's click() to follow an <a> link if I haven't bound an event handler to it with bind or click already?

I have a timer in my JavaScript which needs to emulate clicking a link to go to another page once the time elapses. To do this I'm using jQuery's click() function. I have used $().trigger() and window.location also, and I can make it work as intended with all three.
I've observed some weird behavior with click() and I'm trying to understand what happens and why.
I'm using Firefox for everything I describe in this question, but I am also interested in what other browsers will do with this.
If I have not used $('a').bind('click',fn) or $('a').click(fn) to set an event handler, then calling $('a').click() seems to do nothing at all. It does not call the browser's default handler for this event, as the browser does not load the new page.
However, if I set an event handler first, then it works as expected, even if the event handler does nothing.
$('a').click(function(){return true;}).click();
This loads the new page as if I had clicked the a myself.
So my question is twofold: Is this weird behavior because I'm doing something wrong somewhere? and why does calling click() do nothing with the default behavior if I haven't created a handler of my own?
As Hoffman determined when he tried to duplicate my results, the outcome I described above doesn't actually happen. I'm not sure what caused the events I observed yesterday, but I'm certain today that it was not what I described in the question.
So the answer is that you can't "fake" clicks in the browser and that all jQuery does is call your event handler. You can still use window.location to change page, and that works fine for me.
Another option is of course to just use vanilla JavaScript:
document.getElementById("a_link").click()
Interesting, this is probably a "feature request" (ie bug) for jQuery. The jQuery click event only triggers the click action (called onClick event on the DOM) on the element if you bind a jQuery event to the element. You should go to jQuery mailing lists ( http://forum.jquery.com/ ) and report this. This might be the wanted behavior, but I don't think so.
EDIT:
I did some testing and what you said is wrong, even if you bind a function to an 'a' tag it still doesn't take you to the website specified by the href attribute. Try the following code:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
$(document).ready(function() {
/* Try to dis-comment this:
$('#a').click(function () {
alert('jQuery.click()');
return true;
});
*/
});
function button_onClick() {
$('#a').click();
}
function a_onClick() {
alert('a_onClick');
}
</script>
</head>
<body>
<input type="button" onclick="button_onClick()">
<br>
<a id='a' href='http://www.google.com' onClick="a_onClick()"> aaa </a>
</body>
</html>
It never goes to google.com unless you directly click on the link (with or without the commented code). Also notice that even if you bind the click event to the link it still doesn't go purple once you click the button. It only goes purple if you click the link directly.
I did some research and it seems that the .click is not suppose to work with 'a' tags because the browser does not suport "fake clicking" with javascript. I mean, you can't "click" an element with javascript. With 'a' tags you can trigger its onClick event but the link won't change colors (to the visited link color, the default is purple in most browsers). So it wouldn't make sense to make the $().click event work with 'a' tags since the act of going to the href attribute is not a part of the onClick event, but hardcoded in the browser.
If you look at the code for the $.click function, I'll bet there is a conditional statement that checks to see if the element has listeners registered for theclick event before it proceeds. Why not just get the href attribute from the link and manually change the page location?
window.location.href = $('a').attr('href');
Here is why it doesn't click through. From the trigger function, jQuery source for version 1.3.2:
// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
event.result = false;
// Trigger the native events (except for clicks on links)
if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
this.triggered = true;
try {
elem[ type ]();
// Prevent Internet Explorer from throwing an error for some hidden elements
}
catch (e)
{
}
}
After it calls handlers (if there are any), jQuery triggers an event on the object. However it only calls native handlers for click events if the element is not a link. I guess this was done purposefully for some reason. This should be true though whether an event handler is defined or not, so I'm not sure why in your case attaching an event handler caused the native onClick handler to be called. You'll have to do what I did and step through the execution to see where it is being called.
JavaScript/jQuery doesn't support the default behavior of links "clicked" programmatically.
Instead, you can create a form and submit it. This way you don't have to use window.location or window.open, which are often blocked as unwanted popups by browsers.
This script has two different methods: one that tries to open three new tabs/windows (it opens only one in Internet Explorer and Chrome, more information is below) and one that fires a custom event on a link click.
Here is how:
HTML
<html>
<head>
<script src="jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="script.js" type="text/javascript"></script>
</head>
<body>
<button id="testbtn">Test</button><br><br>
Google<br>
Wikipedia<br>
Stack Overflow
</body>
</html>
jQuery (file script.js)
$(function()
{
// Try to open all three links by pressing the button
// - Firefox opens all three links
// - Chrome only opens one of them without a popup warning
// - Internet Explorer only opens one of them WITH a popup warning
$("#testbtn").on("click", function()
{
$("a").each(function()
{
var form = $("<form></form>");
form.attr(
{
id : "formform",
action : $(this).attr("href"),
method : "GET",
// Open in new window/tab
target : "_blank"
});
$("body").append(form);
$("#formform").submit();
$("#formform").remove();
});
});
// Or click the link and fire a custom event
// (open your own window without following
// the link itself)
$("a").on("click", function()
{
var form = $("<form></form>");
form.attr(
{
id : "formform",
// The location given in the link itself
action : $(this).attr("href"),
method : "GET",
// Open in new window/tab
target : "_blank"
});
$("body").append(form);
$("#formform").submit();
$("#formform").remove();
// Prevent the link from opening normally
return false;
});
});
For each link element, it:
Creates a form
Gives it attributes
Appends it to the DOM so it can be submitted
Submits it
Removes the form from the DOM, removing all traces *Insert evil laugh*
Now you have a new tab/window loading "https://google.nl" (or any URL you want, just replace it). Unfortunately when you try to open more than one window this way, you get an Popup blocked messagebar when trying to open the second one (the first one is still opened).
More information on how I got to this method is found here:
Opening new window/tab without using window.open or window.location.href
Click handlers on anchor tags are a special case in jQuery.
I think you might be getting confused between the anchor's onclick event (known by the browser) and the click event of the jQuery object which wraps the DOM's notion of the anchor tag.
You can download the jQuery 1.3.2 source here.
The relevant sections of the source are lines 2643-2645 (I have split this out to multiple lines to make it easier to comprehend):
// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if (
(!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) &&
elem["on"+type] &&
elem["on"+type].apply( elem, data ) === false
)
event.result = false;
You can use jQuery to select the jQuery object for that element. Then, get the underlying DOM element and call its click() method.
By id:
$("#my-link").each(function (index) { $(this).get(0).click() });
Or use jQuery to click a bunch of links by CSS class:
$(".my-link-class").each(function (index) { $(this).get(0).click() });
Trigger a hyperlink <a> element that is inside the element you want to hookup the jQuery .click() to:
<div class="TopicControl">
<div class="articleImage">
<img src="" alt="">
</div>
</div>
In your script you hookup to the main container you want the click event on. Then you use standard jQuery methodology to find the element (type, class, and id) and fire the click. jQuery enters a recursive function to fire the click and you break the recursive function by taking the event 'e' and stopPropagation() function and return false, because you don't want jQuery to do anything else but fire the link.
$('.TopicControl').click(function (event) {
$(this).find('a').click();
event.stopPropagation();
return false;
});
Alternative solution is to wrap the containers in the <a> element and place 's as containers inside instead of <div>'s. Set the spans to display block to conform with W3C standards.
It does nothing because no events have been bound to the event. If I recall correctly, jQuery maintains its own list of event handlers that are bound to NodeLists for performance and other purposes.
If you need this feature for one case or very few cases (your whole application is not requiring this feature). I would rather leave jQuery as is (for many reasons, including being able to update to newer versions, CDN, etc.) and have the following workaround:
// For modern browsers
$(ele).trigger("click");
// Relying on Paul Irish's conditional class names,
// <https://www.paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/>
// (via HTML5 Boilerplate, <https://html5boilerplate.com/>) where
// each Internet Explorer version gets a class of its version
$("html.ie7").length && (function(){
var eleOnClickattr = $(ele).attr("onclick")
eval(eleOnClickattr);
})()
To open hyperlink in the same tab, use:
$(document).on('click', "a.classname", function() {
var form = $("<form></form>");
form.attr(
{
id : "formid",
action : $(this).attr("href"),
method : "GET",
});
$("body").append(form);
$("#formid").submit();
$("#formid").remove();
return false;
});

Categories