Generate dynamic borders

1

I have the following form:

<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<button>GERAR</button>

In it the user selects the value of the border width in the following block:

<div class="forma"></div>

I created the method gerar()

const gerar = _ => {
  let widths = [];
  cps.forEach(c => widths.push('${c.value}px'));
  frm.style.borderStyle = 'solid';
  frm.style.borderWidth = widths.join(' ');
};

which traverses the object cps and adds its value to the object widths , then sets the property borderWidth to the values of the object widths .

So far so good, as you can see below the code works normally.

let btn = document.querySelector('button');
let cps = document.querySelectorAll('[type="number"]');
let frm = document.querySelector('.forma');

const gerar = () => {
  let widths = [];
  cps.forEach(c => widths.push('${c.value}px'));
  frm.style.borderStyle = 'solid';
  frm.style.borderWidth = widths.join(' ');
};

btn.onclick = gerar;
input[type="number"] {
  width: 40px;
}
.forma {
  height: 100px;
  margin: 14px;
  width: 100px;
}
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<button>GERAR</button>

<div class="forma"></div>

The problem

One of these fields may have its value greater than the others, eg 0 10 60 10 / 50 20 20 40 .

I have to set the borderColor property and the field that has its largest value, will have the different color, eg:

0 10 60 10  = "transparent #f7f7f7 #069 #f7f7f7"
50 20 20 40 = "#069 #f7f7f7 #f7f7f7 #f7f7f7"

How can I resolve?

    
asked by anonymous 26.03.2018 / 05:33

2 answers

1

You can do this: click starts by generating the same color for all borders, whereas the 0px will not be visible. Then find the largest using Math.max on the values of <input> and also find which <input> has the largest, and based on its position assign the borderColor that interests, being this one of the four available:

  • borderTopColor
  • borderRightColor
  • borderBottomColor
  • borderLeftColor

Example:

let btn = document.querySelector('button');
let cps = document.querySelectorAll('[type="number"]');
let frm = document.querySelector('.forma');

const borders = ["borderTopColor", "borderRightColor", 
                 "borderBottomColor", "borderLeftColor"];

const gerar = () => {
  let widths = [];
  cps.forEach(c => widths.push('${c.value}px'));
  frm.style.borderStyle = 'solid';
  frm.style.borderWidth = widths.join(' ');
  frm.style.borderColor = '#b7b7b7'; //aplica a cor normal a todos
  
  //pega em cada um dos inputs e mapeia para um array apenas com os numeros
  let nums = [...cps].map(caixa => Number(caixa.value)); 
  
  let maior = Math.max(...nums); //acha o maior     
  let posicaoMaior = nums.findIndex(x => x === maior); //acha a posição do maior
  frm.style[borders[posicaoMaior]] = '#069'; //mete a cor diferente no maior
};

btn.onclick = gerar;
input[type="number"] {
  width: 40px;
}
.forma {
  height: 100px;
  margin: 14px;
  width: 100px;
}
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<button>GERAR</button>

<div class="forma"></div>

Note: I put a slightly darker gray just to look better.

I found the largest using the spread operator and its position using findIndex .

The above example works for when only one element is larger than the others. If you have the possibility of having more than one, and you want all of them to be bigger, just change the way it is applied, for example using a forEach and comparing each value if it is equal to the greater one: / p>

let btn = document.querySelector('button');
let cps = document.querySelectorAll('[type="number"]');
let frm = document.querySelector('.forma');

const borders = ["borderTopColor", "borderRightColor", 
                 "borderBottomColor", "borderLeftColor"];

const gerar = () => {
  let widths = [];
  cps.forEach(c => widths.push('${c.value}px'));
  frm.style.borderStyle = 'solid';
  frm.style.borderWidth = widths.join(' ');
  frm.style.borderColor = '#b7b7b7'; 
  
  let nums = [...cps].map(caixa => Number(caixa.value)); 
  let maior = Math.max(...nums);

  //aplica o maior agora com um forEach
  cps.forEach((caixa, posicao) => { 
    if (Number(caixa.value) === maior){
      frm.style[borders[posicao]] = '#069';
    }
  });
};

btn.onclick = gerar;
input[type="number"] {
  width: 40px;
}
.forma {
  height: 100px;
  margin: 14px;
  width: 100px;
}
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<input type="number" min="0" value="0" />
<button>GERAR</button>

<div class="forma"></div>
    
26.03.2018 / 12:05
1

I believe you should only store the entry in a {Array} to be able to filter and find the highest value index ... imagining that its input follows the same order scheme defined by the border-color attribute (top, right, bottom, left) you can use reduce() :

let fakeEntires = [13, 8, 13, 2]

function getIndexFromMajor(itens) {
    return itens.reduce((iMax, x, i, arr) => x > arr[iMax] ? i : iMax, 0)
}

let index = getIndexFromMajor(fakeEntires)

console.log('index:${index}, value:${fakeEntires[index]}')

However this method will return only the first occurrence (index) if there are duplicate values, I believe that in this case it would be ideal to not return in this case, you can use the operator "Spread" ... and

26.03.2018 / 11:13