i have a draggable parent with click events on the children. i want to cancel/abort/stop the click event of the child when it’s starting to get dragged, but also don’t want do stop any parent events. Since i don’t use a lot of jQuery, i’d be very thankful for a vanilla javascript solution.
sorry for this newbie question, but i can’t wrap my head around it.
here is what i got so far: JSFiddle
// horizontal drag scroll for items const itemScroll = document.querySelector('#itemScroll'); var isDown = false; var startX; var scrollLeft; itemScroll.addEventListener('mousedown', (e) => { isDown = true; itemScroll.classList.add('active'); startX = e.pageX - itemScroll.offsetLeft; scrollLeft = itemScroll.scrollLeft; }); itemScroll.addEventListener('mouseleave', () => { isDown = false; itemScroll.classList.remove('active'); }); itemScroll.addEventListener('mouseup', () => { isDown = false; itemScroll.classList.remove('active'); }); itemScroll.addEventListener('mousemove', (e) => { if (!isDown) return; e.preventDefault(); const x = e.pageX - itemScroll.offsetLeft; itemScroll.scrollLeft = scrollLeft - (x - startX); }); // click an item to change bg-color const items = document.querySelectorAll('.item'); for (var i = 0; i < items.length; i++) { items[i].addEventListener('click', function (e) { this.classList.toggle('active'); }); }
Advertisement
Answer
Detect movement and in that case “prevent” the default click behaviour programmatically using a global variable. We reset the is_moved
variable when mousedown, and set it when mousemove.
// horizontal drag scroll for items const itemScroll = document.querySelector('#itemScroll'); var isDown = false; var startX; var scrollLeft; var isMoved = false; itemScroll.addEventListener('mousedown', (e) => { isDown = true; isMoved = false; itemScroll.classList.add('active'); startX = e.pageX - itemScroll.offsetLeft; scrollLeft = itemScroll.scrollLeft; }); itemScroll.addEventListener('mouseleave', () => { isDown = false; itemScroll.classList.remove('active'); }); itemScroll.addEventListener('mouseup', () => { isDown = false; itemScroll.classList.remove('active'); }); itemScroll.addEventListener('mousemove', (e) => { if (!isDown) return; isMoved = true; e.preventDefault(); const x = e.pageX - itemScroll.offsetLeft; itemScroll.scrollLeft = scrollLeft - (x - startX); }); // click an item to change bg-color const items = document.querySelectorAll('.item'); for (var i = 0; i < items.length; i++) { items[i].addEventListener('click', function(e) { if (!isMoved) { this.classList.toggle('active'); } }); }
* { box-sizing: border-box; margin: 0; padding: 0; } .mainCont { width: 100%; max-width: 100vw; height: 100vh; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; scroll-snap-align: center; } #itemScroll { cursor: pointer; overflow-x: hidden; } #itemScroll.active { cursor: grabbing; } .itemRow { width: max-content; min-width: 100%; height: 100%; max-height: 400px; padding: 0 5vw; display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 5rem; transform-style: preserve-3d; } .item { width: 100px; height: 100px; max-width: 400px; max-height: 100%; background-color: red; } .item.active { background-color: green; }
<div class="mainCont" id="itemScroll"> <div class="itemRow"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div> </div>