5

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!

Sandy
  • 2,572
  • 7
  • 40
  • 61
  • http://touchpunch.furf.com/ and read the first paragraph as to why they made that script. Its probably the same issue for you. – Jack M. Aug 14 '13 at 22:19

3 Answers3

1

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

Rembunator
  • 1,305
  • 7
  • 13
0

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

Hugo Silva
  • 6,748
  • 3
  • 25
  • 42
  • The touchstart event isn't triggering in mobile from the parent frame. – Sandy Aug 19 '13 at 00:29
  • Do you mean when you trigger it programmatically, or is there an element in the parent frame not capturing the event? Can you provide a sample? – Hugo Silva Aug 19 '13 at 02:17
  • It's basically using the code above. In the parent frame I have a div which when clicked tries to call $('#slider').contents().find("#link1").trigger('touchstart'); of the child frame, but nothing happens. The selector seems ok since I can do stuff like $('#slider').contents().find("#link1").css('border', '2px solid red'); – Sandy Aug 19 '13 at 06:22
  • I ran your example in an Android phone, and the issue I had was something completely different from what I imagined at first. Just added a new answer... hope it helps. – Hugo Silva Aug 19 '13 at 12:04
0

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...

Hugo Silva
  • 6,748
  • 3
  • 25
  • 42