Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to prevent jQueryMobile swipe gesture from bubbling, but it's not working

I'm using jQuery Mobile and created something that somewhat resembles Android Holo Tabs:

http://note.io/18RNMRk

In order to get the swipe gesture to work for switching between tabs, this is the code I've added:

$("#myPage #pageTabs").on('swipeleft swiperight', function(e){
    e.stopPropagation();
    e.preventDefault();
});
$("#myPage").on('swipeleft', function(){
    ui.activities.swipe(1);
}).on('swiperight', function(){
    ui.activities.swipe(-1);
});

With the tabs' HTML resembling:

<div id="pageTabs">
    <div class="tab">
        <a href="#" data-dayOfMonth="26">Thu</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="27">Fri</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="28" data-meridian="am">Sat AM</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="28" data-meridian="pm">Sat PM</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="29">Sun</a>
    </div>
</div>

I'm listening for the swipe gesture at the page-level because the div[data-role=content] can sometimes not fill the screen vertically, if there isn't enough content to do so. If I listened on this div and it was not covering the screen, and you swiped close to the bottom, the event wouldn't fire on this div, it would be on the root page (div[data-role=page]).

Here's Firefox's 3D rendering of that page for proof of the above assertion. I've annotated div[data-role=content]:

http://note.io/18RPhyK

For that reason, I'm listening for it at the page level; but since the number of tabs can scroll out of the viewport (as seen above: Sunday is off-screen to the right), I would like the user to be able to scroll that horizontally as well. I've already got the horizontal scrolling working (that's just some simple CSS), but the problem is that, even with my e.stopPropagation() seen above, the swipe gesture is bubbling up to the page element and my swipe gesture is preventing the smooth scrolling that was available before I added the swipe gesture.

Am I misunderstanding how event bubbling works, or how to stop it in this scenario?

like image 453
Adam Tuttle Avatar asked Jul 31 '13 15:07

Adam Tuttle


1 Answers

I've found a workaround, but an actual solution would be better.

Since the problem is that I don't have a container that fills these two requirements:

  1. contain the page content, but not the tabs
  2. use min-height to always fill the screen vertically

I decided to add a wrapper:

<div id="pageTabs">
    <div class="tab">
        <a href="#" data-dayOfMonth="26">Thu</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="27">Fri</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="28" data-meridian="am">Sat AM</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="28" data-meridian="pm">Sat PM</a>
    </div>
    <div class="tab">
        <a href="#" data-dayOfMonth="29">Sun</a>
    </div>
</div>
<div class="contentWrapper">
    <!-- ... -->
</div>

I've moved my swipe gesture attachment to this new wrapper and removed the swipe listener from the tab bar:

$(".contentWrapper").on('swipeleft', function(){
    ui.activities.swipe(1);
}).on('swiperight', function(){
    ui.activities.swipe(-1);
});

And in order to make sure it always fills the screen, every time the page is loaded, I set its min-height to the calculated height of the viewport minus the wrapper's top offset:

$("#myPage").on('pageshow', function(){

    var viewPortHeight = document.documentElement.clientHeight;
    var offset = $(".contentWrapper", this)[0].offsetTop;

    $(".contentWrapper", this).css({'min-height': viewPortHeight - offset + 'px', 'display': 'block'});
});

This does exactly what I want. I can swipe on the page content to switch tabs, and I can horizontally scroll the tabs without activating a swipe gesture.

For anyone interested in achieving the same effect, here's my LESSCSS:

#pageTabs {
    @tab-highlight: @lightblue;

    margin: -15px -15px 15px -15px;
    padding: 0;
    height: 38px;
    overflow-x: scroll;
    overflow-y: hidden;
    white-space: nowrap;
    border-bottom: 2px solid @tab-highlight;

    .tab {
        display: inline-block;
        vertical-align: top;
        border-left: 1px solid @tab-highlight;
        margin-left: -5px;
        height: 100%;

        &:first-child {
            margin-left: 0;
        }
        &.active {
            height: 32px;
            border-bottom: 8px solid @tab-highlight;
        }
        a {
            padding: 12px 20px 0px 20px;
            display: block;
            height: 100%;
            text-decoration: none;
        }
    }
}
like image 111
Adam Tuttle Avatar answered Oct 29 '22 06:10

Adam Tuttle