Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clicks/taps are passing through absolute positioned divs in JQuery Mobile

I'm not sure if anyone else has experienced this in JQuery Mobile, but for some reason I can't prevent elements underneath my absolute positioned DIVs and fixed header from intercepting clicks/taps on mobile devices.

For example, I have a page that lists contacts in a long scrolling list. On that page is a floating header with a button. If I scroll the list downward and click on the floating header's button, the click will pass through to whatever contact is underneath the header, even though it cannot be visually seen because it is underneath the header.

If I click on a button in the header, the button never triggers - the list element underneath it always fires. If I scroll the list so that there is nothing underneath the header, however, I can click the header's button normally.

So far I've tried: - event.stopPropagation() on the header's button. This never even fired, however. The element underneath always steals focus

  • Detecting the click event's Y coordinates. If the coordinates are less than the height of the floating header, abort the click action. This didn't work either, however - after I did "return true;", the button's click handler never fired.

  • Setting z-indexes on the floating header and list item container, even though they are already visually correct.

I'm quite stumped. I tried to make a testbed but it works correctly there. It also works correctly on the JQM demo site, so it must be something about my app's CSS or structure. I can't think of what would cause floating elements to show correctly but only be tappable when nothing else tappable is underneath them.

Any ideas would be appreciated!

like image 756
Anthony Avatar asked Oct 03 '22 22:10

Anthony


2 Answers

Figured this one out though a long process of elimination. The new "panel" introduced in JQM 1.3 causes problems with fixed headers on mobile devices. Any clicks on the header are ignored, as if the header has a lower z-index than what sits beneath it, even though it is visually on top.

I found the issue by ripping all of the classes off of the ui-panel-content-wrap DIV

var wrapper = $(".ui-panel-content-wrap");
$(wrapper).removeClass('ui-body-c').removeClass('ui-panel-animate').removeClass('ui-panel-content-wrap-closed').removeClass('ui-panel-content-wrap');

Once I did this, it of course broke the panel, but my fixed header was properly clickable again.

From there, I re-introduced each class until I found that "ui-panel-content-wrap" was the offender. I then traced it down to this:

/* hardware acceleration for smoother transitions on WebKit browsers */
.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal),
.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) > div,
.ui-panel-animate.ui-panel-closed.ui-panel-display-reveal > div,
.ui-panel-animate.ui-panel-content-wrap,
.ui-panel-animate.ui-panel-content-fixed-toolbar {
    -webkit-backface-visibility: hidden;
    -webkit-transform: translate3d(0,0,0);
}

If you comment out or override -webkit-transform: translate3d(0,0,0); fixed headers will begin trapping events.

like image 160
Anthony Avatar answered Oct 12 '22 11:10

Anthony


What I did for WP8 was put a backdrop behind your elements that has a click handler. If the click falls through, the element underneath will catch it. Usually there is a backdrop behind modals so that's where I put it. The e.stopPropagation() is overkill but shouldn't hurt. You might also try one of the fixes in the comments. For the element that isn't firing when it should be, I don't know the circumstances but make sure your element is fully loaded before attaching the handler or attach it to the parent with the selector parameter parent.on('click','.button',function(){ //code });

html

<div class="backdrop"></div>

css

.backdrop{
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
}

js

$(document).ready(){
    $('.backdrop').on('click',function(e){
        e.stopPropagation();
        return false;
    }
}

You can also just attach the click handler to the main parent of the elements to prevent it falling through as well.

like image 42
bmasterson Avatar answered Oct 12 '22 11:10

bmasterson