Cancel ng-swipe-right on child
Asked Answered
B

3

6

In my angular application, the body has a ng-swipe right and left to toggle a sidebar. The problem is when in my page I have a scrollable horizontal DIV. It won't scroll because of the swipe of the body.

<body ng-swipe-right="sidebar = true" ng-swipe-left="sidebar = false">
    <div class="scrollable-x">long content that overflow on x</div>
</body>

Is there a way to prevent from swiping and to let the scroll of the child element?

I tried to set $event.stopPropagation() on the swipe of the div so the scrollbar is not toggled anymore but the content won't scroll.

Any idea?

Bateau answered 11/8, 2014 at 10:31 Comment(3)
I have got an idea - why not to create a plnkr/fiddle/whatever?Zedoary
This is quite an old question, I'm not sure the user is still active. I'm interested in a solution, I'll create a fiddle now.Elegit
jsfiddle.net/wmc75s4y Try scrolling from left-right right-left inside the yellow box.Elegit
Z
2

UPDATE

Looked at allenhwkim's answer and indeed he is correct, that $event's propagation can be easily stopped. I took it for granted (without checking), that attaching ng-swipe-* directive to other element will start firing separate events. I was clearly wrong.

HERE is updated fiddle.

The below answer is basically rubbish.

There is still one problem with stopPropagation -- the mouse up event seems not to fire.


The most elegant solution would be to decorate the ng-swipe-* directives or $swipe service -- but looking into their code and I do not think it is possible.

Other option would be to create your own directive, that would manually attach ng-swipe-*, take care of the compilation process and provide desired functionality. Surely, bit complicated.

What I came up with is a quick hack. The idea is to add an attribute to an element whose descendants should not fire the ng-swipe-*.

js

myApp.value('shouldFire', function(element){
     var update = true;

        // strange enough $event.fromElement is always null
        var current = element;
        while(current && current != document.body){
            if(current.getAttribute('swipe')=='cancel'){
                update = false;
                break;
            }
            current = current.parentElement;
        }

        return update;
})

function MyCtrl($scope, shouldFire) {
    $scope.sidebar = false;

    $scope.updateSidebar = function($event, show){

        var element = $event.toElement || $event.srcElement; 
        shouldFire(element) && ($scope.sidebar = show);

    }
}

html

<div class="cont" ng-swipe-right="updateSidebar($event, true)"
    ng-swipe-left="updateSidebar($event, false)">

...

<div class="pan-container" panhandler=""
   content-width="500px" swipe="cancel">

UPDATED DEMO


caution

  1. in android's chrome.v.39 angular-panhandler is broken.
  2. $event stores a proper touch event (android's chrome) or a custom event (desktop's chrome); in the latter case $event.fromElement is always null.
  3. The proposed solution is a quick hack -- it is neither elegant nor general. Nonetheless, theoretically it could be possible to support multi ng-swipe-* handlers by setting different values in swipe attribute.
Zedoary answered 17/12, 2014 at 21:38 Comment(0)
I
1

$event.stopProgagation() must work. I don't know why yours not work.

http://plnkr.co/edit/AqczfhAVGMXNOcJij0JE?p=preview

  var app = angular.module('myApp',['ngTouch']);
  app.controller("MyCtrl", function($scope) {
    $scope.void = function(evt){
      evt.stopPropagation();
    }
  });

The common sense to me is that swiping and scroll left/right are different.

swiping is about moving fast. If you do not move fast. it's not swiping. When you scroll slowly, swiping does not happen.

I think all users know about this(maybe not). If not, I would recommend UX approach to let the user scroll slowly by showing some button or whatever, and leaving swipe as it is.

Anyhow, there is a way to disabling swipe using stopPropagation

Let me know if this plnkr does not satisfy your requirement.

Indecency answered 17/12, 2014 at 22:17 Comment(1)
You are right about stopPropagation. I think you did not save your plnkr properly though. +1Zedoary
O
0

It's like this. In your scrollable element (usually it's the dom element you set as overflow-x: scroll), add ng-swipe-right="preventScrollingFunction($event)", like so:

<div ng-swipe-right="preventScrollingFunction($event)">...</div>

Then, in the scope create the function:

$scope.preventScrollingFunction = function($event) {
    $event.stopPropagation();
}

That should do it!

Note: make sure the parameter for the function is exactly $event, as it is inyected by Angular and if you name it $evt or $e or whatever, it wont work.

Omni answered 21/4, 2017 at 21:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.