1

I am using this code for dragging container left / right. This works well. User can also click on the "thumb". The problem is that click happens also after drag. It should be either drag or click. How can I isolate one or another? It has to work on tablets of course.

var thumbContainer = document.querySelector('.aplbox-thumb-container'),
  thumbContainerWrap = document.querySelector('.aplbox-thumb-container-wrap'),
  startXThumb,
  startTouchThumb

if ("ontouchstart" in window) {
  thumbContainer.addEventListener("touchstart", dragStartThumb);
}
thumbContainer.addEventListener("mousedown", dragStartThumb);


function dragStartThumb(e) {

  if (e.preventDefault) e.preventDefault();
  e.stopPropagation()


  if (!startTouchThumb) {
    startTouchThumb = true;

    document.addEventListener('mousemove', dragMoveThumb)
    document.addEventListener('mouseup', dragEndThumb);

    if ("ontouchstart" in window) {
      document.addEventListener('touchmove', dragMoveThumb)
      document.addEventListener('touchend', dragEndThumb);
    }

    var point;
    if (e.type == 'touchstart') {
      var touches = e.changedTouches;

      if (touches.length > 1) {
        return false;
      }
      point = touches[0];
      e.preventDefault();
    } else {
      point = e;
      e.preventDefault();
    }

    var currX = thumbContainer.style.transform.replace(/[^\d.]/g, '');
    currX = parseInt(currX) || 0;

    startXThumb = point.pageX + currX;

  }

}

function dragMoveThumb(e) {
  if (startTouchThumb) {

    var point;
    if (e.type == 'touchmove') {
      var touches = e.changedTouches;

      if (touches.length > 1) {
        return false;
      }
      point = touches[0];
      e.preventDefault();
    } else {
      point = e;
      e.preventDefault();
    }

    var diff = point.pageX - startXThumb;

    if (diff > 0) diff = 0;
    else if (diff < -thumbContainer.offsetWidth + thumbContainerWrap.offsetWidth) diff = -thumbContainer.offsetWidth + thumbContainerWrap.offsetWidth;

    thumbContainer.style.transform = 'translateX(' + diff + 'px)';

  }

}

function dragEndThumb(e) {

  e.stopPropagation()

  if (startTouchThumb) {
    startTouchThumb = false;

    document.removeEventListener('mousemove', dragMoveThumb)
    document.removeEventListener('mouseup', dragEndThumb);

    if ("ontouchstart" in window) {
      document.removeEventListener('touchmove', dragMoveThumb)
      document.removeEventListener('touchend', dragEndThumb);
    }

  }
}

//click thumb
thumbContainerWrap.addEventListener('click', function(e) {


  if (e.target.closest('.aplbox-thumb')) {



    console.log('click')

  }

})
.aplbox-thumb-container-wrap {
  position: absolute;
  top: 0;
  left: 0;
  background-color: #ccc;
  width: 100%;
  height: 100px;
  overflow: hidden;
  box-sizing: border-box;
}

.aplbox-thumb-container {
  position: relative;
  padding: 5px 0;
  height: 100%;
  display: flex;
  flex-direction: row;
  transform: translateX(0);
  touch-action: none;
}

.aplbox-thumb {
  width: 100px;
  height: 70px;
  margin-right: 5px;
  box-sizing: border-box;
  background: #333;
  flex-shrink: 0;
  overflow: hidden;
  margin-bottom: 5px;
}
<div class="aplbox-thumb-container-wrap">
  <div class="aplbox-thumb-container" style="width: 1300px;">
    <div class="aplbox-thumb" data-id="0"></div>
    <div class="aplbox-thumb" data-id="1"></div>
    <div class="aplbox-thumb" data-id="2"></div>
    <div class="aplbox-thumb" data-id="3"></div>
    <div class="aplbox-thumb" data-id="4"></div>
    <div class="aplbox-thumb" data-id="5"></div>
    <div class="aplbox-thumb" data-id="6"></div>
    <div class="aplbox-thumb" data-id="7"></div>
    <div class="aplbox-thumb" data-id="8"></div>
    <div class="aplbox-thumb" data-id="9"></div>
    <div class="aplbox-thumb" data-id="10"></div>
    <div class="aplbox-thumb" data-id="11"></div>
  </div>
</div>
Toniq
  • 4,492
  • 12
  • 50
  • 109
  • 1
    Did you try using flag? you can set flag false on touchstart then set it true on touchend. and for click set condition ```if ( ! flag) return``` – Amirhoseinh73 Jan 14 '23 at 11:35
  • 1
    Hope this helps. https://stackoverflow.com/a/19431746/20946150 Good luck! – Srikanth Jan 14 '23 at 11:41
  • @Amirhoseinh73 Yes, the same demo Lukas wrote below , but click is not registered on mobile. – Toniq Jan 14 '23 at 17:51

1 Answers1

2

Declare the variable moved. In the dragStartThumb function set this variable to false, and in the dragMoveThumb function set it to true and in the onclick event check this variable. Like below.
Something like @Amirhoseinh73 wrote, but instead of setting the flag to true in the touchend function we set the flag to true in the mousemove function, because we don't want have always variable set to true.

var thumbContainer = document.querySelector('.aplbox-thumb-container'),
  thumbContainerWrap = document.querySelector('.aplbox-thumb-container-wrap'),
  startXThumb,
  startTouchThumb
  
let moved = false;

if ("ontouchstart" in window) {
      thumbContainer.addEventListener("touchstart", dragStartThumb);
}
    
thumbContainer.addEventListener("mousedown", dragStartThumb);


function dragStartThumb(e) {
   moved = false;
   
  //if (e.preventDefault) e.preventDefault();
  e.stopPropagation()

  if (!startTouchThumb) {
    startTouchThumb = true;

    document.addEventListener('mousemove', dragMoveThumb)
    document.addEventListener('mouseup', dragEndThumb);

    if ("ontouchstart" in window) {
      document.addEventListener('touchmove', dragMoveThumb)
      document.addEventListener('touchend', dragEndThumb);
    }

    var point;
    if (e.type == 'touchstart') {
      var touches = e.changedTouches;

      if (touches.length > 1) {
        return false;
      }
      point = touches[0];
      //e.preventDefault();
    } else {
      point = e;
      //e.preventDefault();
    }

    var currX = thumbContainer.style.transform.replace(/[^\d.]/g, '');
    currX = parseInt(currX) || 0;

    startXThumb = point.pageX + currX;

  }

}

function dragMoveThumb(e) {
  moved = true;
    
  if (startTouchThumb) {

    var point;
    if (e.type == 'touchmove') {
      var touches = e.changedTouches;

      if (touches.length > 1) {
        return false;
      }
      point = touches[0];
      e.preventDefault();
    } else {
      point = e;
      e.preventDefault();
    }

    var diff = point.pageX - startXThumb;

    if (diff > 0) diff = 0;
    else if (diff < -thumbContainer.offsetWidth + thumbContainerWrap.offsetWidth) diff = -thumbContainer.offsetWidth + thumbContainerWrap.offsetWidth;

    thumbContainer.style.transform = 'translateX(' + diff + 'px)';

  }

}

function dragEndThumb(e) {
e.stopPropagation()
  if (startTouchThumb) {
    startTouchThumb = false;

    document.removeEventListener('mousemove', dragMoveThumb)
    document.removeEventListener('mouseup', dragEndThumb);

    if ("ontouchstart" in window) {
      document.removeEventListener('touchmove', dragMoveThumb)
      document.removeEventListener('touchend', dragEndThumb);
    }

  }
}

//click thumb
thumbContainerWrap.addEventListener('click', function(e) {
  if (e.target.closest('.aplbox-thumb') && !moved) {

    console.log('click')

  }

})
.aplbox-thumb-container-wrap {
  position: absolute;
  top: 0;
  left: 0;
  background-color: #ccc;
  width: 100%;
  height: 100px;
  overflow: hidden;
  box-sizing: border-box;
}

.aplbox-thumb-container {
  position: relative;
  padding: 5px 0;
  height: 100%;
  display: flex;
  flex-direction: row;
  transform: translateX(0);
  touch-action: none;
}

.aplbox-thumb {
  width: 100px;
  height: 70px;
  margin-right: 5px;
  box-sizing: border-box;
  background: #333;
  flex-shrink: 0;
  overflow: hidden;
  margin-bottom: 5px;
}
<div class="aplbox-thumb-container-wrap">
  <div class="aplbox-thumb-container" style="width: 1300px;">
    <div class="aplbox-thumb" data-id="0"></div>
    <div class="aplbox-thumb" data-id="1"></div>
    <div class="aplbox-thumb" data-id="2"></div>
    <div class="aplbox-thumb" data-id="3"></div>
    <div class="aplbox-thumb" data-id="4"></div>
    <div class="aplbox-thumb" data-id="5"></div>
    <div class="aplbox-thumb" data-id="6"></div>
    <div class="aplbox-thumb" data-id="7"></div>
    <div class="aplbox-thumb" data-id="8"></div>
    <div class="aplbox-thumb" data-id="9"></div>
    <div class="aplbox-thumb" data-id="10"></div>
    <div class="aplbox-thumb" data-id="11"></div>
  </div>
</div>
Lukas
  • 2,263
  • 1
  • 4
  • 15
  • But click doesnt work when I test on mobile . The same when I use device toolbar on chrome and test this demo. – Toniq Jan 14 '23 at 17:03
  • @Toniq you can't use e.preventDefault() in touchstart event, because it suppresses the onclick event. I have updated my answer. More here: https://stackoverflow.com/questions/6780965/why-onclick-event-suppressed-when-preventdefault-is-called-for-the-touchstart. – Lukas Jan 14 '23 at 19:52
  • It does work now, and with stopPropagation on start and end events, plus preventDefault in move event. Thats a lot to know. – Toniq Jan 14 '23 at 20:40