jQuery touchSwipe event on element prevents scroll
Asked Answered
G

3

1

I have some list of div elements ordered vertically. Using jQuery TouchSwipe plugin added swipe event to catch left-right swipe. Idea was to remove element from list by swiping it left or right side like this:

enter image description here

Finally I got something like this:

$(function() {

  $('.swElement').swipe({
      swipeStatus: function(event, phase, direction, distance, duration, fingerCount) {
        console.log(distance);
        if (phase == "move") {
          if (direction == "right") {
            $(this).css({
              'right' : (distance*-1)+'px'
            });  
          }
        } else if (phase == "cancel") {
          $(this).css({
              'right' : 0
          });
        } else if (phase == "end") {
          $(this).animate({
              'right' : '-100%'
          }, 200, function() {
             $(this).remove();
          });
        } else {
           //?????
        }
      },
      threshold: 150,
      maxTimeThreshold: 5000,
	  fingers: 'all'
  });
  
});
.swElement {
  display: block;
  width: 100%;
  height: 50px;
  border: 1px solid black;
  box-sizing: border-box;
  padding: 0 10px;
  line-height: 50px;
  cursor: pointer;
  position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://dl.dropboxusercontent.com/u/2130702/cdn/jquery.touchSwipe.min.js"></script>

<h2>Swipe right to remove element</h2>

<div class="swElement">Element</div>
<div class="swElement">Element</div>
<div class="swElement">Element</div>
<div class="swElement">Element</div>
<div class="swElement">Element</div>

Problem

It's working great on mobile chrome browser, but prevents up/down scroll on native android browser.

I understand that this swipeStatus catch both left/right and up/dmown directions, but don't know how to prevent is from it - I need only right swipe event.

Any ideas? Thanks in advance.

Update

I can't use jQuery mobile framework, because it conflict's with other scripts which I have to use. Maybe there will be another way to figure out?

Gleanings answered 30/4, 2015 at 11:10 Comment(0)
A
3

This is not answering the actual problem for your question, but is an alternative to touch plugging(s). You can still use them for other things in the same app or website.

Coincidence the other day i was having a look at this (jquery-mobile-swipe-list) https://github.com/ksloan/jquery-mobile-swipe-list/blob/master/index.html and this demo http://jsbin.com/luzunu/1/edit?html,css,js,output which uses some Math to detect horizontal touch.

I Created two demos. One that reveals whats behind the elements like the picture in your question and another to drag/swipe to delete like in the code you have.

Any problems with elements flickering using -webkit-transform: translateZ(0); transform: translateZ(0); fixes the flickers.

Demo drag/swipe to reveal behind. i put in a delay of 5 seconds for the touch events to start.

https://jsfiddle.net/4gk27ru1/

Code

    var startPos;
    var handlingTouch = false;
    var itemis;
    setTimeout(function() {

    document.addEventListener('touchstart', function(e) {
      // Is this the first finger going down? 

      if (e.touches.length == e.changedTouches.length) {
        startPos = {
          x: e.touches[0].clientX,
          y: e.touches[0].clientY
        };
      }
    });

    document.addEventListener('touchmove', function(e) {
      // If this is the first movement event in a sequence:
      if (startPos) {
        // Is the axis of movement horizontal?
        if (Math.abs(e.changedTouches[0].clientX - startPos.x) > Math.abs(e.changedTouches[0].clientY - startPos.y)) {
          handlingTouch = true;
          e.preventDefault();
          onSwipeStart(e);
        }
        startPos = undefined;
      } else if (handlingTouch) {
        e.preventDefault();
        onSwipeMove(e);
      }
    });

    document.addEventListener('touchend', function(e) {
      if (handlingTouch && e.touches.length == 0) {
        e.preventDefault();
        onSwipeEnd(e);
        handlingTouch = false;
      }
    });



    function slide(x) {

// slide the element

    $(itemis).css({transform: "translatex("+x+"px)"})
    }

    var swipeOrigin, x, itempos;
    function onSwipeStart(e) {

// find what element is been touched. In your case it may be closest("swElement") but you need to test

      itemis = $(e.target).closest("li").find(".move")

      swipeOrigin = e.touches[0].clientX;
    }
    function onSwipeMove(e) {
      x = e.touches[0].clientX - swipeOrigin;
      slide(x);
    }
    function onSwipeEnd(e) {

    //On Touch End if x (distance traveled to the right) is greater than +35 pixels then slide element  +100 pixels.

      if (x > 35) { 
    slide(100);
      }
      else {
      slide(0);
    }
    }
    }, 5000);

Because the movement of pixels are either in plus or minus to prevent the movement of the elements from either side its easy when using an if statement. Other conditions can be applied using if/else if

Example

move the element from left to right (---->) if plus pixels touched. The Opposite way right to left (<-----) is less than 1 pixel i.e (x < 1)

if (x > 1) { 
 slide(x);
  }

https://jsfiddle.net/v5Ldovmj/

Demo 2 Slide to Delete

https://jsfiddle.net/afkdtjh9/

Additions

// detect window width to fly out the items from whatever the devices window  width is. 

var itemwidth = $(window).width();

// slide item to windows width wait half a second, slide it up and remove from the DOM

slide(itemwidth);
setTimeout(function() {
$(itemis).slideUp("fast").remove()
}, 500);

You can use jquery animate or a pluging like velocity js to control the speed of the elements moving so its smoother as using css transform by itself feels very fast

Altruist answered 30/4, 2015 at 13:50 Comment(4)
Thanks for answer and for time that you spend for such a big answer. Unfortunately I forgot to mention that I can't use jQuery mobile framework. It conflicts with others that I have to use. Considering on your answer, I'll try to figure out some other way. Thank a lot.Gleanings
@ zur4ik You don't need JQM. The code is plain Javascript and some Jquery so it can be used for anything and any touch device. I'm just using JQM for the easy fancy list items. Ill do a simple demo with divs and without JQMAltruist
@ zur4ik here you go jsfiddle.net/y8L1vhd0 -- using no frameworks just plain html. as i mentioned in the answer in this instance the ( -webkit-transform: translateZ(0); transform: translateZ(0);) came in handy because without it the positioning of the divs causes flickers when dragged.Altruist
@Gleanings no problem. I use touchswipe and hammer js for certain apps, but getting to know plain javascript touch events leverages the use of plugings and in some cases its better so your app doesn't get bloated with unnecessary code although both touch plugings are very good.Altruist
I
2

Its simpler than all the answers above. Just add this parameter and you'll be good to go :

    allowPageScroll:"vertical"
Impure answered 9/2, 2016 at 17:48 Comment(0)
B
1
if (direction == "left"){
   return false;
}

Prevents any events when swiping to the left

Burrill answered 28/12, 2015 at 16:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.