JS Переключение класса между несколькими активными элементами

122
17 сентября 2019, 12:30

на странице есть блок с 5 слайдами:

<div class="block__slides" id="slider1">
        <div class="block__slide slide-active"></div>
        <div class="block__slide slide-active"></div>
        <div class="block__slide slide-active"></div>
        <div class="block__slide "></div>
        <div class="block__slide "></div>
</div>

Только три из них являются активными.

также есть две кнопки:

 <button class="block__control" id="left-slider-button"></button>
 <button class="block__control" id="right-slider-button"></button>

как сделать код который будет при клике на кнопку вправо :

  • искать первый элемент block__slides
  • убирать у него класс slide__active
  • искать ближайший элемент после слайда с классом slide__active и добавлять ему этот класс (так чтобы отображалось всегда три слайда)
  • если это последний слайд у родителя с классом slide__active то он должен переставлять его снова на первый элемент чтобы получался круг

И аналогичную функцию для кнопки влево.

вообще я верно понимаю реализацию этого процесса?

Буду благодарен за помощь с примерами кода.

Answer 1

Через "пятое колено", конечно... Но, как вариант:

var aSlides, mSlides = []; 
window.onload = function() { 
   
  aSlides = Array.prototype.slice.call(document.getElementById('slider1').querySelectorAll('.block__slide')); 
  aSlides.forEach(function(el) { 
    mSlides.push((el.classList.contains('slide-active')) ? '1' : '0'); 
  }); 
 
  document.querySelector('div.block__controls').addEventListener('click', function(ev) { 
    if (ev.target.id == 'left-slider-button') { fShiftSlides(false); } 
    if (ev.target.id == 'right-slider-button') { fShiftSlides(true); } 
  }); 
} 
 
function fShiftSlides(bDirection) { 
  if (bDirection) { mSlides.unshift(mSlides.pop()); }  
  else { mSlides.push(mSlides.shift()); } 
 
  aSlides.forEach(function(el, index) { 
    if (mSlides[index] == '1') { el.classList.add('slide-active'); }  
    else { el.classList.remove('slide-active'); } 
  }); 
}
.block__slides, 
.block__controls { 
  display: flex; 
  justify-content: space-around; 
  align-items: center; 
} 
 
.block__slide { 
  height: 50px; 
  width: 50px; 
  box-sizing: border-box; 
  border: 2px solid #090; 
  border-radius: 50%; 
  text-align: center; 
  transition: .5s ease; 
} 
.slide-active { 
  height: 100px; 
  width: 100px; 
  border-radius: 0%; 
} 
 
.block__control { 
  height: 25px; 
  width: 50%; 
  margin: 15px; 
}
<div class="block__slides" id="slider1"> 
  <div class="block__slide slide-active">1</div> 
  <div class="block__slide slide-active">2</div> 
  <div class="block__slide slide-active">3</div> 
  <div class="block__slide ">4</div> 
  <div class="block__slide ">5</div> 
</div> 
<div class="block__controls"> 
  <button class="block__control" id="left-slider-button">&lt;</button> 
  <button class="block__control" id="right-slider-button">&gt;</button> 
</div>

Количество блоков может быть любым.

Вариант с таймером:

var tSlides, aSlides, mSlides = []; 
window.onload = function() { 
   
  aSlides = Array.prototype.slice.call(document.getElementById('slider1').querySelectorAll('.block__slide')); 
  aSlides.forEach(function(el) { 
    mSlides.push((el.classList.contains('slide-active')) ? '1' : '0'); 
  }); 
 
  document.querySelector('div.block__controls').addEventListener('click', function(ev) { 
    if (ev.target.id == 'left-slider-button') { clearInterval(tSlides); fShiftSlides(false); } 
    if (ev.target.id == 'right-slider-button') { clearInterval(tSlides); fShiftSlides(true); } 
    if (document.getElementById('timer-slider-button').checked) { 
      tSlides = setInterval(function() { fShiftSlides(true); }, 2000); 
    } else { 
      clearInterval(tSlides); 
    } 
  }); 
} 
 
function fShiftSlides(bDirection) { 
  if (bDirection) { mSlides.unshift(mSlides.pop()); }  
  else { mSlides.push(mSlides.shift()); } 
 
  aSlides.forEach(function(el, index) { 
    if (mSlides[index] == '1') { el.classList.add('slide-active'); }  
    else { el.classList.remove('slide-active'); } 
  }); 
}
.block__slides, 
.block__controls { 
  display: flex; 
  justify-content: space-around; 
  align-items: center; 
} 
 
.block__slide { 
  height: 50px; 
  width: 50px; 
  box-sizing: border-box; 
  border: 2px solid #090; 
  border-radius: 50%; 
  text-align: center; 
  transition: .5s ease; 
} 
.slide-active { 
  height: 100px; 
  width: 100px; 
  border-radius: 0%; 
} 
 
.block__control { 
  height: 25px; 
  width: 50%; 
  margin: 15px; 
}
<div class="block__slides" id="slider1"> 
  <div class="block__slide slide-active">1</div> 
  <div class="block__slide slide-active">2</div> 
  <div class="block__slide slide-active">3</div> 
  <div class="block__slide ">4</div> 
  <div class="block__slide ">5</div> 
</div> 
<div class="block__controls"> 
  <button class="block__control" id="left-slider-button">&lt;</button> 
  <input type="checkbox" class="block__control" id="timer-slider-button"> 
  <button class="block__control" id="right-slider-button">&gt;</button> 
</div>

Вариант для нескольких слайдеров и анимацией таймера:

'use strict'; 
window.onload = function() { 
  /* Находим и перебираем все слайдеры на странице */ 
  Array.prototype.slice.call(document.querySelectorAll('.block__slider')).forEach(function(elSlider) { 
    // Временный массив для начального состояния слайдов 
    let mSlides = []; 
    /* Находим и перебираем все слайды в конкретном блоке слайдов */ 
    Array.prototype.slice.call(elSlider.querySelectorAll('.block__slide')).forEach(function(elSlide) { 
      // Заносим в массив начальное состояние слайдов 
      mSlides.push((elSlide.classList.contains('slide-active')) ? '1' : '0'); 
    }); 
    // Сохраняем значения массива в пользовательском атрибуте 
    elSlider.setAttribute('data-shift', mSlides.join('')); 
    /* Делегируем обработчик клика блоку с кнопками */ 
    elSlider.querySelector('div.block__controls').addEventListener('click', function(ev) { 
      // Если нажата левая кнопка 
      if (ev.target.classList.contains('left-slider-button')) { 
        // Останавливаем таймер 
        clearInterval(this.tSlides); 
        // Удаляем анимацию таймера 
        this.classList.remove('timer-active'); 
        // Вызываем функцию сдвига 
        fShiftSlides(this.parentElement, false); 
      } 
      // Если нажата правая кнопка 
      if (ev.target.classList.contains('right-slider-button')) { 
        clearInterval(this.tSlides); 
        this.classList.remove('timer-active'); 
        fShiftSlides(this.parentElement, true); 
      } 
      // Если отмечен таймер 
      if (this.querySelector('.timer-slider-button').checked) { 
        // Запускаем таймер с функцией сдвига 
        this.tSlides = setInterval(fShiftSlides, 2500, this.parentElement, true); 
        // Добавляем анимацию таймера 
        this.classList.add('timer-active'); 
      } else { 
        clearInterval(this.tSlides); 
        this.classList.remove('timer-active'); 
      } 
    }); 
  }); 
} 
 
/* Функция сдвига и назначения классов */ 
function fShiftSlides(oSlider, bDirection) { 
  // Временный массив состояний слайдов 
  let mSlides = oSlider.getAttribute('data-shift').split(''); 
  // Изменяем массив в соответствии с направлением 
  if (bDirection) { 
    // Сдвиг вправо 
    mSlides.unshift(mSlides.pop()); 
  } else { 
    // Сдвиг влево 
    mSlides.push(mSlides.shift()); 
  } 
  /* Находим и перебираем все слайды в конкретном блоке слайдов */ 
  Array.prototype.slice.call(oSlider.querySelectorAll('.block__slide')).forEach(function(el, index) { 
    // Изменяем классы у слайдов на основании значений массива 
    if (mSlides[index] == '1') { 
      el.classList.add('slide-active'); 
    } else { 
      el.classList.remove('slide-active'); 
    } 
  }); 
  // Сохраняем изменённый массив 
  oSlider.setAttribute('data-shift', mSlides.join('')); 
}
.block__slides, 
.block__controls { 
  display: flex; 
  justify-content: space-around; 
  align-items: center; 
  margin: 8px 0; 
} 
 
.block__slide { 
  height: 50px; 
  width: 50px; 
  box-sizing: border-box; 
  border: 2px solid #090; 
  border-radius: 50%; 
  text-align: center; 
  box-shadow: 0 2px 10px -3px black; 
  transition: .5s ease; 
} 
 
.slide-active { 
  height: 100px; 
  width: 100px; 
  border-radius: 0%; 
  box-shadow: 0 15px 20px -10px rgba(0, 0, 0, 0.4); 
} 
 
.block__control { 
  height: 25px; 
  width: 50%; 
  margin: 10px 15px 15px; 
} 
 
.timer-active { 
  background-image: linear-gradient(to left, #f00, #fa0, #0a0); 
  background-size: 0% 2px; 
  background-repeat: no-repeat; 
  background-position: 0 0; 
  animation: timer 2.5s ease-in-out infinite; 
} 
 
@keyframes timer { 
  0% { background-size: 0% 2px; } 
  100% { background-size: 100% 2px; } 
}
<div class="block__slider" id="slider1"> 
  <div class="block__slides"> 
    <div class="block__slide slide-active">1</div> 
    <div class="block__slide slide-active">2</div> 
    <div class="block__slide slide-active">3</div> 
    <div class="block__slide ">4</div> 
    <div class="block__slide ">5</div> 
  </div> 
  <div class="block__controls"> 
    <button class="block__control left-slider-button">&lt;</button> 
    <input class="block__control timer-slider-button" type="checkbox"> 
    <button class="block__control right-slider-button">&gt;</button> 
  </div> 
</div> 
<div class="block__slider" id="slider2"> 
  <div class="block__slides"> 
    <div class="block__slide slide-active">1</div> 
    <div class="block__slide slide-active">2</div> 
    <div class="block__slide slide-active">3</div> 
    <div class="block__slide ">4</div> 
    <div class="block__slide ">5</div> 
  </div> 
  <div class="block__controls"> 
    <button class="block__control left-slider-button">&lt;</button> 
    <input class="block__control timer-slider-button" type="checkbox"> 
    <button class="block__control right-slider-button">&gt;</button> 
  </div> 
</div>

Код не большой, просто раздулся от комментариев :-)

Answer 2

Немного переделал код @UModeL. Что бы работало для нескольких слайдеров. Нужно обернуть каждый слайдер в блок с классом .slider__holder. Так же убрал айди с кнопок и добавил классы .button-left .button-right

window.addEventListener("load", function() { 
        var sliderHolders = [...document.querySelectorAll(".slider__holder")]; 
        sliderHolders.forEach(elem => init(elem)); 
 
        function init(elem) { 
          var aSlides, 
            mSlides = []; 
          aSlides = Array.prototype.slice.call( 
            elem.querySelectorAll(".block__slide") 
          ); 
          aSlides.forEach(function(el) { 
            mSlides.push(el.classList.contains("slide-active") ? "1" : "0"); 
          }); 
 
          elem 
            .querySelector(".block__controls") 
            .addEventListener("click", function(ev) { 
              if (ev.target.classList.contains("button-left")) { 
                fShiftSlides(false); 
              } 
              if (ev.target.classList.contains("button-right")) { 
                fShiftSlides(true); 
              } 
            }); 
 
          function fShiftSlides(bDirection) { 
            if (bDirection) { 
              mSlides.unshift(mSlides.pop()); 
            } else { 
              mSlides.push(mSlides.shift()); 
            } 
 
            aSlides.forEach(function(el, index) { 
              if (mSlides[index] == "1") { 
                el.classList.add("slide-active"); 
              } else { 
                el.classList.remove("slide-active"); 
              } 
            }); 
          } 
        } 
      });
.block__slides, 
      .block__controls { 
        display: flex; 
        justify-content: space-around; 
        align-items: center; 
      } 
 
      .block__slide { 
        height: 50px; 
        width: 50px; 
        box-sizing: border-box; 
        border: 2px solid #090; 
        border-radius: 50%; 
        text-align: center; 
        transition: 0.5s ease; 
      } 
      .slide-active { 
        height: 100px; 
        width: 100px; 
        border-radius: 0%; 
      } 
 
      .block__control { 
        height: 25px; 
        width: 50%; 
        margin: 15px; 
      }
<div class="slider__holder"> 
      <div class="block__slides"> 
        <div class="block__slide slide-active">1</div> 
        <div class="block__slide slide-active">2</div> 
        <div class="block__slide slide-active">3</div> 
        <div class="block__slide ">4</div> 
        <div class="block__slide ">5</div> 
      </div> 
      <div class="block__controls"> 
        <button class="block__control button-right"> 
          &lt; 
        </button> 
        <button class="block__control button-left"> 
          &gt; 
        </button> 
      </div> 
    </div> 
    <div class="slider__holder"> 
      <div class="block__slides"> 
        <div class="block__slide slide-active">1</div> 
        <div class="block__slide slide-active">2</div> 
        <div class="block__slide slide-active">3</div> 
        <div class="block__slide ">4</div> 
        <div class="block__slide ">5</div> 
      </div> 
      <div class="block__controls"> 
        <button class="block__control button-right"> 
          &lt; 
        </button> 
        <button class="block__control button-left"> 
          &gt; 
        </button> 
      </div> 
    </div>

READ ALSO
jquery datatable refresh

jquery datatable refresh

есть две таблицы, которые заполняются сходя из результатов одного аякс запросакак обновить таблицу после повторно аякса запроса?

76
Сложение квадратов цифр числах, пока не станет 1

Сложение квадратов цифр числах, пока не станет 1

Нужно написать функцию, которая возьмет число, и сложит квадрат каждой его цифры, пока не станет 1, если конечно с этим числом это возможноНапример:

79
Как парсить csv json-парсером от OKTELL

Как парсить csv json-парсером от OKTELL

Товарищи, ниже у меня есть пример, для парсера в Oktell, как мне заставить его читать файлcsv?

78