Vanilla JS - slider - Active dots

Asked by At

Please, can you help me assign .active class to slider Dots, which are generated by JS, they are not part of HTML. When slide 1 is active, I need dot 1 to have class .active, but no luck.. all solutions I have foud are for dots hardcoded in HTML.

My HTML:

  <div class="w3-content w3-display-container">
    <div class="w3-display-container mySlides">
        <div class="w3-display-bottomleft w3-large w3-container w3-padding-16 w3-black">
            <h3>Slide 1</h3>
            <p>1. Lorem Ipsum.</p>
        </div>
    </div>
    <div class="w3-display-container mySlides">
        <div class="w3-display-bottomright w3-large w3-container w3-padding-16 w3-black">
            <h3>Slide 2</h3>
            <p>2.Lorem Ipsum.</p>
        </div>
    </div>
    <div class="w3-display-container mySlides">
        <div class="w3-display-topleft w3-large w3-container w3-padding-16 w3-black">
            <h3>Slide 3</h3>
            <p>3. Lorem Ipsum.</p>
        </div>
    </div>
    <button class="w3-button w3-display-left w3-black" onclick="plusDivs(-1)">&#10094;</button>
    <div id="js-slider-dots"></div>
    <button class="w3-button w3-display-right w3-black" onclick="plusDivs(1)">&#10095;</button>
  </div>

My JS (which switch the slides and generate dots):

var slideIndex = 1;
showDivs(slideIndex);

function plusDivs(n) {
    showDivs(slideIndex += n);
}

function goToDiv(n) {
    showDivs(slideIndex = n);
}

function showDivs(n) {
    var i;
    var x = document.getElementsByClassName("mySlides");
    if (n > x.length) { slideIndex = 1 }
    if (n < 1) { slideIndex = x.length }
    for (i = 0; i < x.length; i++) {
        x[i].style.display = "none";
    }
    x[slideIndex - 1].style.display = "block";
}

function generateDots() {
    var i;
    var x = document.getElementsByClassName("mySlides");
    for (i = 0; i < x.length; i++) {
        var dotNumber = i + 1;
        var dot = document.createElement('span');
        dot.innerHTML =
            '<button class="js-dot" onclick="goToDiv(' + dotNumber + ')">' + dotNumber + '</button>';

        document.getElementById('js-slider-dots').appendChild(dot);

    }
}
generateDots();

It is also all live on JS Bin: https://jsbin.com/ketohatane/edit?html,js,output

2 Answers

1
FZs On Best Solutions

You can easily do it by .classList.add() and .remove().

Just select the dots, and activate the dot that belongs to the active slide at showDivs:

function showDivs(n) {
    var i;
    var x = document.getElementsByClassName("mySlides");
    //get the list of dots
    var y = document.getElementById("js-slider-dots").children;
    if (n > x.length) { slideIndex = 1 }
    if (n < 1) { slideIndex = x.length }
    for (i = 0; i < x.length; i++) {
        x[i].style.display = "none";
        //remove .active from all dots
        y[i].classList.remove("active")
    }
    x[slideIndex - 1].style.display = "block";
    //add .active to the selected dot
    y[slideIndex - 1].classList.add("active")
}

See this snippet:

var slideIndex = 1;

function plusDivs(n) {
 showDivs(slideIndex += n);
}

function goToDiv(n) {
 showDivs(slideIndex = n);
}

function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
//get the list of dots
var y = document.getElementById("js-slider-dots").children;
if (n > x.length) { slideIndex = 1 }
if (n < 1) { slideIndex = x.length }
for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
    //remove .active from all dots
    y[i].classList.remove("active")
}
x[slideIndex - 1].style.display = "block";
//add .active to the selected dot
y[slideIndex - 1].classList.add("active")
}

function generateDots() {
 var i;
 var x = document.getElementsByClassName("mySlides");
 for (i = 0; i < x.length; i++) {
  var dotNumber = i + 1;
  var dot = document.createElement('span');
  dot.innerHTML =
   '<button class="js-dot" onclick="goToDiv(' + dotNumber + ')">' + dotNumber + '</button>';

  document.getElementById('js-slider-dots').appendChild(dot);

 }
}
generateDots();
//placed AFTER generateDots()
showDivs(slideIndex);
/* Just for illustration */
.active{outline:solid 1px red;}
  <div class="w3-content w3-display-container">
 <div class="w3-display-container mySlides">
  <div class="w3-display-bottomleft w3-large w3-container w3-padding-16 w3-black">
   <h3>Slide 1</h3>
   <p>1. Lorem Ipsum.</p>
  </div>
 </div>
 <div class="w3-display-container mySlides">
  <div class="w3-display-bottomright w3-large w3-container w3-padding-16 w3-black">
   <h3>Slide 2</h3>
   <p>2.Lorem Ipsum.</p>
  </div>
 </div>
 <div class="w3-display-container mySlides">
  <div class="w3-display-topleft w3-large w3-container w3-padding-16 w3-black">
   <h3>Slide 3</h3>
   <p>3. Lorem Ipsum.</p>
  </div>
 </div>
 <button class="w3-button w3-display-left w3-black" onclick="plusDivs(-1)">&#10094;</button>
 <div id="js-slider-dots"></div>
 <button class="w3-button w3-display-right w3-black" onclick="plusDivs(1)">&#10095;</button>
  </div>

0
Rowan Baker-French On

If you access the DOM from your goToDiv function, you can be sure that you are accessing the DOM after it has been updated with your class="js-dot" elements.

Something like this will give you the functionality you want.

function goToDiv(n) {
    showDivs(slideIndex = n);
    var dots = document.getElementsByClassName('js-dot');
    for(var i = 0; i < dots.length; i++) {
      if (i == n - 1) {
        dots[i].classList.add('active');
      } else {
        dots[i].classList.remove('active');
      }
    }
}

Here it is in action: https://jsbin.com/tekukebeye/1/edit?html,js,output