Sandy
Sandy

Reputation: 2692

JQuery click event not working for iframe, in mobile browser

This is a pretty specific issue I'm having, but I'm out of ideas on how to debug this, or even find out if it will work at all on mobile browsers.

I have 2 pages (both on the SAME domain, so I don't have issues with the cross-domain security policy), one is in an iframe inside the other. Since I need to catch clicks on both the parent and the child, I created a div that covers the iframe, and then calls the click method on the child element:

Here's a demo code I made:

Parent file:

<script>
$(document).ready(function()
{
    $("#floating_play_button").click(function()
    {
        alert("just clicked floating_play_button... will try to click iframe's on click for link2");
        $('#slider').contents().find("#link1").click();
    });
});
</script>

<div id="floating_play_button" style="cursor:pointer; left: 0px; top:0px; width:100%; height:395px; position:absolute; border:2px solid red;"></div>
<iframe id="slider" src="slider_test.php" width="957" height="337" frameBorder="1" style="border:2px solid green;" ></iframe>

Child page:

<script>
$(document).ready(function()
{
    $("#link1").click(function()
    {
        alert("#link1 clicked...");
    });
});
</script>

<div id="link1">
    <a href="#">Link 1</a><br />
</div>

This works fine on all desktop browsers, but not on Chrome for Android (version from July 22 2013) the default Android browser, iPad, nor iPhone.

In the child page I tried both of these forms but neither work:

    $(document).on('click', '#link1', function()
    {
        alert("on click activated for link1");
    });

    $("#link1").click(function()
    {
        alert("#link1 clicked...");
    });

As an additional note, the selector is fine. I can do things like change the text attributes and similar via jQuery and it works fine. I just can't call the click event.

Any tips or pointers?

Thanks!

Upvotes: 5

Views: 5772

Answers (3)

Hugo Silva
Hugo Silva

Reputation: 6958

There are two instances of jQuery being loaded. One in the parent and one inside the iframe. Things get messed up somewhere between generating the event on parent's instance and handling on child's.

If you dispatch the event without using jQuery's event engine, it works:

$("#floating_play_button").click(function(){
    //$('#slider').contents().find("#link1").click(); // instead:
    var newEvent = document.createEvent('Event');
    newEvent.initEvent('click',true,true);
    $('#slider').contents().find("#link1").first()[0].dispatchEvent(newEvent);
});

But jQuery handles a whole lot of stuff, like cross browser compatibility, that we don't wanna miss. So, just make sure your event is being created and handled by the same jQuery instance, and it should work:

$("#floating_play_button").click(function(){
    //$('#slider').contents().find("#link1").click(); // instead:
    window.frames['slider'].$('#link1').click();
});

EDIT 1

I couldn't figure out what exactly breaks, but I noticed that the browsers where it failed, didn't implement the Event constructor. Events were created using document.createEvent instead. So my guess would be that some reference gets lost along the way by using the wrong document object. If someone can explain in deep, please do...

Upvotes: 0

Rembunator
Rembunator

Reputation: 1315

Chrome doesn't allow accessing the contents of an iframe. Even if the contents have the same origin.

You should use postMessage to communicate between frames.

Maybe this helps: cross-window-messaging-with-postmessage

Upvotes: 1

Hugo Silva
Hugo Silva

Reputation: 6958

My answer is based on ios because that is all I have available, but might be the same for android.

Click events work a little differently on touch enabled devices. There is no mouse, so technically there is no click. According to this article - http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html - due to memory limitations, click events are only emulated and dispatched from anchor and input elements. Any other element could use touch events, or have click events manually initialized by adding a handler to the raw html element, for example, to force click events on divs:

$('div').each(function(){
    this.onclick = function() {}
});

Now click will be triggered by divs, therefore can be listened by jQuery.


On your case, you could just change the listener to the anchor element:

$("#link1 a").click(function()
{
    alert("#link1 clicked...");
});

Or use a touch event on the div:

$(document).on('touchstart', '#link1', function()
{
    alert("on click activated for link1");
});

then trigger like this:

$('#slider').contents().find("#link1").trigger('touchstart');

Here is a fiddle with a few experiments, might be helpful - http://jsbin.com/ukalah/9/edit

Upvotes: 0

Related Questions