Skip to content
Advertisement

Restrict the scope of functions in JavaScript ( Slider Use Case )?

In the following script, the code works when there is a slider, but when the number of sliders on a page is more than one, the next sliders do not work.

How can this script be changed when we have more than one slider on the page so that each slider ” Draggable Feature “ works separately and does not overlap?

What changes are needed to make this code “Draggable feature” work separately for each slider?

How can I handle this with ” querySelectorAll ” and ” forEach ” ?

const slider = document.querySelector('.items');
let isDown = false;
let startX;
let scrollLeft;

slider.addEventListener('mousedown', (e) => {
  isDown = true;
  slider.classList.add('active');
  startX = e.pageX - slider.offsetLeft;
  scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', () => {
  isDown = false;
  slider.classList.remove('active');
});
slider.addEventListener('mouseup', () => {
  isDown = false;
  slider.classList.remove('active');
});
slider.addEventListener('mousemove', (e) => {
  if (!isDown) return;
  e.preventDefault();
  const x = e.pageX - slider.offsetLeft;
  const walk = (x - startX) * 3; //scroll-fast
  slider.scrollLeft = scrollLeft - walk;
});
.items,
.items_1 {
  position: relative;
  width: 90%;
  background: green;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
  transition: all 0.2s;
  transform: scale(0.98);
  will-change: transform;
  user-select: none;
  cursor: pointer;

  margin: 2rem auto;
  border: 3px solid violet;

}

.item {
  display: inline-block;
  background: red;
  min-height: 50px;
  min-width: 150px;
  margin: .5rem;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>slider</title>
  <link rel="stylesheet" href="./style.css">
</head>


<body>

  <div class="items">

    <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 class="item "></div>

  </div>


  <div class="items">

    <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 class="item "></div>

  </div>

  <div class="items">

    <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 class="item "></div>

  </div>


  <script src="./script.js"></script>

</body>

</html>

Advertisement

Answer

How can I handle this with ” querySelectorAll ” and ” forEach ” ?

Just put your code that declares the state variables and attaches the event handlers to one slider into such a loop:

const sliders = document.querySelectorAll('.items');
for (const slider of sliders) {
  let isDown = false;
  let startX;
  let scrollLeft;

  slider.addEventListener('mousedown', (e) => {
    isDown = true;
    slider.classList.add('active');
    startX = e.pageX - slider.offsetLeft;
    scrollLeft = slider.scrollLeft;
  });
  slider.addEventListener('mouseleave', () => {
    isDown = false;
    slider.classList.remove('active');
  });
  slider.addEventListener('mouseup', () => {
    isDown = false;
    slider.classList.remove('active');
  });
  slider.addEventListener('mousemove', (e) => {
    if (!isDown) return;
    e.preventDefault();
    const x = e.pageX - slider.offsetLeft;
    const walk = (x - startX) * 3; //scroll-fast
    slider.scrollLeft = scrollLeft - walk;
  });
}
.items {
  position: relative;
  width: 90%;
  background: green;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space: nowrap;
  transition: all 0.2s;
  transform: scale(0.98);
  will-change: transform;
  user-select: none;
  cursor: pointer;

  margin: 2rem auto;
  border: 3px solid violet;

}
.items.active {
  border-color: blue;
}

.item {
  display: inline-block;
  background: red;
  min-height: 50px;
  min-width: 150px;
  margin: .5rem;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>slider</title>
  <link rel="stylesheet" href="./style.css">
</head>


<body>

  <div class="items">

    <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 class="item "></div>

  </div>


  <div class="items">

    <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 class="item "></div>

  </div>

  <div class="items">

    <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 class="item "></div>

  </div>


  <script src="./script.js"></script>

</body>

</html>
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement