Как обновить входной[тип=»диапазон»] атрибут «значение» при нажатии на div?

#javascript #html #css

Вопрос:

Я работаю над пользовательским слайдером диапазона для своего веб-сайта. Все работает нормально, но я застрял, чтобы сделать возможным, чтобы при нажатии на определенный ползунок поля(ввод[тип=»диапазон»]) обновлялся в соответствии со значением метки данных этого конкретного div, так что нам не нужно перетаскивать большой палец слайдера, чтобы обновить пользовательскую панель? .Прилагается исходный код, в котором я поделился тем, чего я достиг до сих пор, и тем, что осталось, Для удобства я установил непрозрачность ввода диапазона на 0,1, чтобы вы могли получить представление о том, что происходит в бэкэнде. Любые предложения или помощь будут оценены по достоинству. Спасибо!

 const rangeSlider = document.querySelector('#price_slider');
rangeSlider.addEventListener("input", rangeScript);
const customProgress = document.querySelector('#customProgress');

for(let i = 0; i < rangeSlider.max - rangeSlider.min ; i  ){
  const step = document.createElement('div');
  step.classList.add('step');
  step.setAttribute('data-label',  rangeSlider.min   i   1);
  customProgress.appendChild(step);
}

customProgress.querySelector(`.step[data-label="${rangeSlider.value}"]`)
.classList.add('current')

function rangeScript(value){ 
  const target = document.getElementById('progress'); 
  
  let newValue = parseInt(this.value);
  const currentStep = customProgress.querySelector(`.step.current`);
  if (currentStep) {
    currentStep.classList.remove('current');
  }
  

nextStep = customProgress.querySelector(`.step[data-label="${newValue}"]`);

if (nextStep) {
  nextStep.classList.add('current')

}

} 
 #customProgress {
display: flex;
width: 100%;
height: 25px;
background: transparent;
}

.step {
  position: relative;
  background: yellow;
  height: 100%;
  width: 100%;
  border-right: 1px solid black;
}

.step::after {
  content: attr(data-label);
  position: absolute;
  top: -1em;
  right: -.25em;
}

.step ~ .current,
.step.current {
  background: blue;
} 
 <h1>what I have achieved</h1>
<div id="customProgress">
  
</div> 
<div id="progress" style=" width: 100%;" > 
<input id="price_slider" type="range" min="4" max="9" value="" style="opacity: 0.1; width: 100%; height: 50px" /> 
</div> 

Ответ №1:

Ключ состоит в том, чтобы добавить прослушиватель событий в step divs. Он «слышит» щелчок, получает собственное значение из data-label набора данных, применяет это значение к элементу диапазона, а затем, наконец, запускает обработчик rangeScript событий. rangeScript Обработчик необходимо было настроить для работы с event (e). Прослушиватели событий передают один аргумент в своих функциях, event и элемент, который вызвал прослушиватель, всегда event.target является .

 step.addEventListener('click', (e) => {
    let val = e.target.dataset.label;
    document.querySelector('#price_slider').value = val
    rangeScript({target: rangeSlider}) // trigger the event using an adhoc representation of the rangeSlider event object
  })
 
 const rangeSlider = document.querySelector('#price_slider');
rangeSlider.addEventListener("input", rangeScript);
const customProgress = document.querySelector('#customProgress');

for (let i = 0; i < rangeSlider.max - rangeSlider.min; i  ) {
  const step = document.createElement('div');
  step.classList.add('step');
  step.setAttribute('data-label',  rangeSlider.min   i   1);
  step.addEventListener('click', (e) => {
    let val = e.target.dataset.label;
    document.querySelector('#price_slider').value = val
    rangeScript({
      target: rangeSlider
    })
  })
  customProgress.appendChild(step);
}

customProgress.querySelector(`.step[data-label="${rangeSlider.value}"]`)
  .classList.add('current')

function rangeScript(e) {
  const target = document.getElementById('progress');
  let newValue = parseInt(e.target.value);
  const currentStep = customProgress.querySelector(`.step.current`);
  if (currentStep) {
    currentStep.classList.remove('current');
  }
  nextStep = customProgress.querySelector(`.step[data-label="${newValue}"]`);
  if (nextStep) {
    nextStep.classList.add('current')
  }
} 
 #customProgress {
  display: flex;
  width: 100%;
  height: 25px;
  background: transparent;
}

.step {
  position: relative;
  background: yellow;
  height: 100%;
  width: 100%;
  border-right: 1px solid black;
}

.step::after {
  content: attr(data-label);
  position: absolute;
  top: -1em;
  right: -.25em;
}

.step~.current,
.step.current {
  background: blue;
} 
 <h1>what I have achieved</h1>
<div id="customProgress">

</div>
<div id="progress" style=" width: 100%;">
  <input id="price_slider" type="range" min="4" max="9" value="" style="opacity: 0.1; width: 100%; height: 50px" />
</div> 

Комментарии:

1. Спасибо! вы только что очень хорошо объяснили решение проблемы! Высоко оценено.

Ответ №2:

Решение с использованием метода forEach() .

 const rangeSlider = document.querySelector("#price_slider");
rangeSlider.addEventListener("input", rangeScript);
const customProgress = document.querySelector("#customProgress");

for (let i = 0; i < rangeSlider.max - rangeSlider.min; i  ) {
    const step = document.createElement("div");
    step.classList.add("step");
    step.setAttribute("data-label",  rangeSlider.min   i   1);
    customProgress.appendChild(step);
}

customProgress.querySelector(`.step[data-label="${rangeSlider.value}"]`).classList.add("current");

function rangeScript(value) {
    const target = document.getElementById("progress");

    let newValue = parseInt(this.value);
    const currentStep = customProgress.querySelector(`.step.current`);
    if (currentStep) {
        currentStep.classList.remove("current");
    }

    nextStep = customProgress.querySelector(`.step[data-label="${newValue}"]`);

    if (nextStep) {
        nextStep.classList.add("current");
    }
}

const sections = document.querySelectorAll("#customProgress .step");
sections.forEach(function (section) {
    section.addEventListener("click", function () {
        sections.forEach(function (section) {
            section.classList.remove("current");
        });
        this.classList.add("current");
        rangeSlider.value = this.getAttribute("data-label");
    });
}); 
 #customProgress {
    display: flex;
    width: 100%;
    height: 25px;
    background: transparent;
}

.step {
    position: relative;
    background: yellow;
    height: 100%;
    width: 100%;
    border-right: 1px solid black;
}

.step::after {
    content: attr(data-label);
    position: absolute;
    top: -1em;
    right: -0.25em;
}

.step ~ .current,
.step.current {
    background: blue;
} 
 <h1>what I have achieved</h1>
<div id="customProgress"></div>
<div id="progress" style="width: 100%;">
    <input id="price_slider" type="range" min="4" max="9" value="" style="opacity: 0.1; width: 100%; height: 50px;" />
</div>