Can I disable IE10 history swipe gesture?

2019-01-22 03:47发布

I have a surface web app that uses touch panning (container divs have "overflow: auto" style) and I'm using the built-in paging scroll styles:

-ms-scroll-snap-points-x: snapInterval(0px, 1366px);
-ms-scroll-snap-type: mandatory;

My app has a 300% width child container resulting in 3 pages that snap on page boundaries.

This works great for high-performance paging scrolling, except when the user is on the first page and they swipe to the right, which activates the browser's built-in back gesture, exiting my web app and going into the user's IE10 history.

I'm able to disable the back gesture using:

-ms-touch-action: none;

But that also disables touch scrolling so the page is no longer draggable. If I use:

-ms-touch-action: pan-x;

Then the scrolling works again but the browser back gesture reappears which is a really annoying user experience. Is there a way to allow panning but not the history gesture?

5条回答
Anthone
2楼-- · 2019-01-22 04:01

On a project I was working on needed exactly this but needed to scroll in certain areas (not just general scrolling but overflow). Seems the following does work, tested on IE11 (Metro) Surface 2 and IE11 WinPhone on Lumia 930. Also with touch mouse which does the horizontal scrolling too.

Please see this demo here: http://jsbin.com/fediha/1/edit?html,css,output

The trick to disable history back/forward) seems to be to disable "pan-x" on any element except the ones you want to scroll horizontally. Excerpt from CSS:

    * {
      /* disallow pan-x! */
      touch-action: pan-y pinch-zoom double-tap-zoom;
      /* maybe add cross-slide-x cross-slide-y? */
    }
    .scroller-x,
    .scroller-x * {
      /* horizontal scrolling only */
      touch-action: pan-x;
    }
    .scroller-y,
    .scroller-y * {
      /* vertical scrolling only */
      touch-action: pan-y;
    }

On rare instances history back is still triggered but that is really rare (could only do this by wildly flicking on the tablet and even then not it does only happen sometimes).

touch-action is IE11 only, on IE10 you'd need -ms-touch-action but IE10 is not used that much anymore and I have no test device with it.

查看更多
孤傲高冷的网名
3楼-- · 2019-01-22 04:02

The solution is simple, you just need to add a CSS style that prevents scroll behavior from bubbling up from child elements that have reached their scroll limit, to parent elements (where the scroll eventually turns into a top-level history navigation).

The docs (http://msdn.microsoft.com/en-us/library/windows/apps/hh466007.aspx) state that the default is:

-ms-scroll-chaining: none;

However the default appears to really be:

-ms-scroll-chaining: chained;

I set that style to none by default and chained on the elements in my carousel that really should be chained, which disabled history navigation gestures in my app:

* {
    -ms-scroll-chaining: none;
}

.carousel * {
    -ms-scroll-chaining: chained;
}
查看更多
Root(大扎)
4楼-- · 2019-01-22 04:02

Edit: The following doesn't prevent swipe causing navigation on Windows Phone 8.1, although it does prevent swipe navigation for me on a windows 8.1 tablet. Leaving answer here, since it might be partially useful to someone.

If your page is larger than the viewport (touch to pan), then the following CSS works (edit: only on 8.1 tablet):

html {
  -ms-scroll-chaining: none;
}

If your page is smaller than then viewport (i.e. the page is not scrollable/pannable e.g. zoomed out) then the above doesn't work.

However code similar to the following works (edit: only on 8.1 tablet) for me:

CSS:

html.disable-ie-back-swipe {
    overflow: scroll;
    -ms-scroll-chaining: none;
}

JavaScript:

if (navigator.msMaxTouchPoints) {
    if (/Windows Phone/.test(navigator.userAgent)) {
        document.documentElement.classList.add('disable-ie-back-swipe');
    } else {
        try {
            var metroTestElement = document.createElement('div');
            metroTestElement.style.cssText = 'position:absolute;z-index:-1;top:0;right:0;bottom:-10px;width:1px';
            document.body.appendChild(metroTestElement);
            if (Math.round(window.outerWidth - metroTestElement.offsetLeft) === 1) {
                document.documentElement.classList.add('disable-ie-back-swipe');
            }
            document.body.removeChild(metroTestElement);
        } catch (e) {   // window.outerWidth throws error if in IE showModalDialog
        }
    }
}

Notes on the JavaScript:

  • Testing navigator.msMaxTouchPoints checks that this is IE10/IE11 and that the device uses touch.
  • Edit: detects Windows Phone and sets disable-ie-back-swipe however the CSS doesn't actually disable the feature on Windows Phone 8.1 ARRRGH.
  • The metroTestElement tests for modern (modern doesn't have scrollbars so right is 1 pixel, whereas desktop has scrollbars so right is 18 pixels or so depending on scrollbar width).
  • The code only disables the back swipe if IE11 and modern is used.
  • It seems that either html or body can be used for the CSS rules, and I am unsure which is actually better (IMHO I usually think of the body as the page and not scrollable, and html as the viewport/window, but actually depends upon IE implementation details).

Edit 2: This IE feature is called "flip ahead". Corporates may be able to disable it using group policy - see http://www.thewindowsclub.com/enable-disable-flip-feature-internet-explorer-10

查看更多
孤傲高冷的网名
5楼-- · 2019-01-22 04:18

You need to set -ms-touch-action: none; on all elements.

This will instead fire events to your JavaScript handlers, (if there are any), but will prevent ALL new actions including: panning, zooming, and sliding. This is best if you'd like to custom tailor how your app utilizes touch.

查看更多
劫难
6楼-- · 2019-01-22 04:26

Not an ideal or elegant solution, but can you use the MSPointerDown, MSPointerMove and MSPointerUp event listeners to detect a swipe and preventDefault?

// Touch events
target.addEventListener('MSPointerDown', callback);
target.addEventListener('MSPointerMove', callback);
target.addEventListener('MSPointerUp', callback);
查看更多
登录 后发表回答