33

I have a piece of JavaScript that dynamically creates an A tag inside of an existing div and then calls the jQuery function "click" on it. This works as intended in all browsers except Safari.

Safari returns the following error:

'undefined' is not a function (evaluating '$('.shell a')[0].click()')

Any ideas on what I'm doing wrong or why this doesn't work in Safari and how to get it to work (or one piece of code that works in all browsers) I've tried using .trigger("click") as well and it gives the same error.

JavaScript

function writeAndClickLink(url) {

    $('.shell').html('<a href="' + url + '"></a>');
    $('.shell a')[0].click();
}

and in the HTML:

<div class="shell"></div>

The reason I'm doing it this weird way is the function is called from a Flash site to open a twitter window where I am giving a reward for tweeting. This so far has been the only way I could get the "tweet" event to bind to the window. If I open the window any other way (window.open for example) it doesn't capture the bound event that lets me know they actually completed the tweet.

The flow is something like:

  • User clicks tweet button in flash
  • Flash calls javascript function to dynamically write href and "click" it
  • Twitter window opens
  • User successfully tweets
  • Tweet event is captured and updates flash with success
  • Content is unlocked in flash
Scott
  • 948
  • 2
  • 13
  • 25
  • Why `[0]`? That's probably not what you want. – elclanrs Oct 16 '12 at 23:57
  • I finally figured out that the click() call would work if I called it closer to the user click event or tap on the screen. If I first sent a packet to the server for validation and then called click() when it returned, then it wouldn't work. I have to change my logic or flow. – Martin Lottering Sep 26 '15 at 08:23

4 Answers4

33
var a = $('.shell a')[0];
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);
a.dispatchEvent(evObj);

See http://www.howtocreate.co.uk/tutorials/javascript/domevents (search for "Manually firing events").

Trevor Dixon
  • 23,216
  • 12
  • 72
  • 109
  • I was doing the same thing only using "HTMLEvents", the MouseEvents seems to be the difference. – Scott Oct 17 '12 at 01:07
  • 1
    initMouseEvent apparently wants more parameters in Firefox – Alex W Feb 03 '15 at 20:25
  • 1
    @AlexW I had the same problem and I found a nice (short and sweet) fix and explanation here: https://webmynd.wordpress.com/2011/06/15/gotcha-firing-mouse-events-chrome-vs-firefox/ – Klik Mar 26 '15 at 18:09
  • @Klik Yeah I just went to the [MDN page](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent) for initMouseEvent and added in all of the default values as parameters, which I think is exactly what that post is doing. I just wanted to make everyone aware that Firefox has different behavior than e.g. Chrome and the above code won't run as is. Surprisingly, the method is now deprecated entirely, in favor of [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent) too. – Alex W Mar 26 '15 at 18:22
  • 3
    This answer worked at the time, but `initMouseEvent` is deprecated. – Muhammad Abdul-Rahim Dec 04 '15 at 16:45
8

Trevor Dixon's answer does fix Safari, but breaks in even the latest Firefox:

TypeError: Not enough arguments to MouseEvent.initMouseEvent

The best way to support Safari—without breaking Firefox—would be using initEvent instead of initMouseEvent like so:

var element = document.getElementById('your_id_here');
if(element.click)
    element.click();
else if(document.createEvent)
{
    var eventObj = document.createEvent('MouseEvents');
    eventObj.initEvent('click',true,true);
    element.dispatchEvent(eventObj);
}

To update for 2016, MouseEvent should be used instead of initMouseEvent which is deprecated:

var eventObj = new MouseEvent("click", {
    bubbles: true,
    cancelable: true
});
element.dispatchEvent(eventObj);
Alex W
  • 37,233
  • 13
  • 109
  • 109
6

$('.shell a')[0] gets a DOM object out of the jQuery object. That DOM object only has DOM methods (not jQuery methods) and there is no industry standard .click() method on an <a> element until HTML5 and it is not yet implemented in every browser - thus you will see incomplete implementation across difference browsers.

You have a couple choices. The first option gets a jQuery object and uses the .click() method on the jQuery object. This will only work reliably if you are triggering jQuery click handlers, not if you just want the default click for the <a> tag.

function writeAndClickLink(url) {

    $('.shell').html('<a href="' + url + '"></a>');
    $('.shell a').eq(0).click();
}

Or, if clicking the URL is just going to go to a new web page, don't even bother modifying the DOM and just set window.location as there is no point in modifying the DOM at all if you're just going to a new web page:

function writeAndClickLink(url) {
    window.location = url;    
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • +1, excellent answer even though you didn't put the usual level of explanations. `=]` – Fabrício Matté Oct 17 '12 at 00:16
  • @FabrícioMatté - added some more explanation. – jfriend00 Oct 17 '12 at 00:27
  • I've removed my answer as per OP's update this seems more of a XY problem, but you retain my +1 as your code is exactly what I'd initially post. – Fabrício Matté Oct 17 '12 at 00:29
  • I tried adding .eq(0).click() earlier (after finding a similar question and solution here on StackOverflow) but it still doesn't work in Safari. – Scott Oct 17 '12 at 00:41
  • @Scott - did you read my post? I said the eq(0).click() would only work if you are trying to trigger jQuery click handlers, not if you're trying to click the link. – jfriend00 Oct 17 '12 at 01:24
3

$('.shell a')[0] returns the native DOM element which dosn't have jQuery methods bound to it

Remove the "[0]" to keep the jQuery object in order to use jQuery methods

 $('.shell a').click()
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • When I remove the [0] it doesn't work in any browser, so maybe I'm going about this in the wrong way to begin with? – Scott Oct 16 '12 at 23:58
  • 1
    @Scott: Calling jQuery's click does not trigger the default behaviour of the browser. You have to redirect it yourself. There are a couple of related questions, e.g. http://stackoverflow.com/questions/1421584/how-can-i-simulate-a-click-to-an-anchor-tag. – Felix Kling Oct 16 '12 at 23:59
  • 1
    if intent is to do a redirect you already have the url variable to pass to `location` object `window.location=url` – charlietfl Oct 17 '12 at 00:03
  • I'm not trying to redirect, and I don't want to move them away from the page. I added some additional info about why I'm going about it this way. – Scott Oct 17 '12 at 00:12
  • It really has nothing to do with Flash as Flash is just calling the javascript function (and passing it the parameters for the url). The flash just means I can't have a traditional tag. If I call the function directly from the html it's the same problem. – Scott Oct 17 '12 at 00:23
  • what about wrapping the `$('.shell a').click()` in a function and call that function from your flash code? – charlietfl Oct 17 '12 at 00:29
  • Also as I mentioned, if I don't include the [0] it doesn't work in any browser. I tried (as Felix Kling mentioned) dispatching the event myself, but then the tweet event dispatched by Twitter isn't captured. Using $('.shell a')[0].click() has so far been the only way I've been able to pop a new window open and actually capture when they click the tweet button (in all browsers EXCEPT Safari, that is) – Scott Oct 17 '12 at 00:35
  • trigggring a click should be 100% cross browaser. DEMO http://jsfiddle.net/5JP5C/ – charlietfl Oct 17 '12 at 00:48
  • @Scott You say `$('.shell a').click()` and `$('.shell a').eq(0).click()` don't work in any browser. What's the error message for these commands? Is there one? – Jan Oct 17 '12 at 00:57
  • By "don't work" I meant they aren't doing what I was expecting. They give no error (so technically they are working?) but it doesn't provide the same action as if someone had clicked the link. – Scott Oct 17 '12 at 01:04