1

I have an array of inputs, after looping through them using a for loop, is it possible to store each value into a variable?

Here's what I am trying to do specifically: I am building a gradient background generator. I have a total of 6 inputs (rgb for the first color of the gradient and rgb for the second one). I loop through the input array and then I stored each value into a variable (r, g, b, r2, g2, b2) and then use them in the linear-gradient css.

My method doesn't seem to be very functional, so I was wondering if it was possible to store all the input[i] values "automatically" into variables.

const inputs = document.querySelectorAll('input')
const body = document.body;

for (var i = 0; i < inputs.length; i++) {
  inputs[i].addEventListener('change', changeValue);
  inputs[i].addEventListener('mousemove', changeValue);

  function changeValue() {
    let r = inputs[0].value;
    let g = inputs[1].value;
    let b = inputs[2].value;
    let rgb = r + ',' + g + ',' + b;

    let r2 = inputs[3].value;
    let g2 = inputs[4].value;
    let b2 = inputs[5].value;
    let rgb2 = r2 + ',' + g2 + ',' + b2;

    body.style.backgroundImage = `linear-gradient(45deg, rgb(${rgb}), rgb(${rgb2}))`;
  };
}
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">

<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">

1
  • 1
    I would use an object rather than an array. Also, I think that given the number of variables it's perfectly reasonable as it is. Commented Jan 28, 2019 at 16:33

4 Answers 4

2

You can remove all the for loops, by utilizing Array.prototype.forEach and Array.prototype.slice.

I also created a custom shiv (aka polyfill) for EventTarget.prototype.addEventListeners.

EventTarget.prototype.addEventListeners = function(eventNames, listener) {
  eventNames.split(' ').forEach(event => this.addEventListener(event, listener, false))
}

const inputs = document.querySelectorAll('input')

inputs.forEach(input => input.addEventListeners('change mousemove', onChangeValue))

function onChangeValue() {
  let rgb1 = [].slice.call(inputs, 0, 3).map(x => x.value).join(',')
  let rgb2 = [].slice.call(inputs, 3, 6).map(x => x.value).join(',')
  document.body.style.backgroundImage = `linear-gradient(45deg, rgb(${rgb1}), rgb(${rgb2}))`;
};
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">

You could also try to group the components by classes.

EventTarget.prototype.addEventListeners = function(events, listener) {
  events.split(' ').forEach(event => this.addEventListener(event, listener, false));
}

document.querySelectorAll('.color-slider-channel').forEach(input => {
  input.addEventListeners('change mousemove', onChangeValue);
})

function onChangeValue(e) {
  document.body.style.backgroundImage = `linear-gradient(45deg, ${retrieveGradientStops()})`;
};

function retrieveGradientStops() {
  return [...document.querySelectorAll('.color-slider-rgb')].map(s => {
    return 'rgb(' + [...s.querySelectorAll('.color-slider-channel')].map(c => c.value).join(',') + ')';
  }).join(', ');
}
<div class="color-sliders">
  <div class="color-slider-rgb">
    <input type="range" class="color-slider-channel" min="0" max="255">
    <input type="range" class="color-slider-channel" min="0" max="255">
    <input type="range" class="color-slider-channel" min="0" max="255">
  </div>
  <div class="color-slider-rgb">
    <input type="range" class="color-slider-channel" min="0" max="255">
    <input type="range" class="color-slider-channel" min="0" max="255">
    <input type="range" class="color-slider-channel" min="0" max="255">
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! That was exactly what I was looking for. I am going to study your answer as there were a few things I didn't know about. Thanks again!
1

If you're using ES6 you can use a destructuring assignment.

You would do something like:

let [r, g, b, r2, g2, b2] = Array.from(inputs).map((x) => x.value);

Example:

const arr = [234,124,233, 25,233,21]

let [r, g, b, r2, g2, b2] = arr;

console.log(r, g, b)
console.log(r2, g2, b2)

Comments

0

You can simplify your code by using Array destructuring:

const inputs = [...document.querySelectorAll('input')];
const body = document.body;

for (var i = 0; i < inputs.length; i++) {
  inputs[i].addEventListener('change', changeValue);
  inputs[i].addEventListener('mousemove', changeValue);

  function changeValue() {
    let [r, g, b, r2, g2, b2] = inputs.map((x) => x.value);

    let rgb = r + ',' + g + ',' + b;
    let rgb2 = r2 + ',' + g2 + ',' + b2;

    body.style.backgroundImage = `linear-gradient(45deg, rgb(${rgb}), rgb(${rgb2}))`;
  };
}
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">

<input type="range" min="0" max="255">
<input type="range" min="0" max="255">
<input type="range" min="0" max="255">

Comments

0

You could get the values by their id.

function changeValue() {
    const mapId = id => document.getElementById(id).value || 0;
    var [rgb, rgb2] = inputs.map(groups => groups.map(mapId).join(','));

    document.body.style.backgroundImage = `linear-gradient(45deg, rgb(${rgb}), rgb(${rgb2}))`;
}

var inputs = [['r1', 'g1', 'b2'], ['r2', 'g2', 'b2']];

inputs.forEach(group => group.forEach(id => {
    document.getElementById(id).addEventListener('change', changeValue);
    document.getElementById(id).addEventListener('mousemove', changeValue);
}));
<input id="r1" type="range" min="0" max="255">
<input id="g1" type="range" min="0" max="255">
<input id="b1" type="range" min="0" max="255"><br>
<input id="r2" type="range" min="0" max="255">
<input id="g2" type="range" min="0" max="255">
<input id="b2" type="range" min="0" max="255">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.