0

I don't know how to go about calculating the price of 4 select options,

So as you can see in the HTML code, there's 5 divisions to a rank, and a total of 5 ranks.

A guide on the input of Bronze 5 to Bronze 1 would = ($0 + $2 + $4 + $4 + $8)

Bronze Division 5 = $0

Bronze Division 4 = $2

Bronze Division 3 = $4

Bronze Division 2 = $6

Bronze Division 1 = $8

Silver Would also be the same with different prices, and so on to diamond.

Another example is here: https://i.gyazo.com/177ce3443967600e12a4d42636a5db69.png

This shows an order of bronze division 5, to silver division 3. It runs through all the stored prices for each division on the selected rank and adds them until it reaches the last input.

I hope this is enough information to help you understand what I mean.

var current_division,
    desired_division;

    
    
function current1() {
  var Amt = document.priceCalc.CRANK1;
  var Qty = document.priceCalc.CRANK2;
  return parseInt(Qty.value) * parseFloat(Amt.value);
}

function desiredd() {
  var Amt = document.priceCalc.DRANK1;
  var Qty = document.priceCalc.DRANK2;
  return price = parseInt(Qty.value) * parseFloat(Amt.value);

}

function total() {
  if (isNaN(current1())) {
    current_division = 0;
  } else {
    current_division = current1();
  }

  if (isNaN(desiredd())) {
    desired_division = 0;
  } else {
    desired_division = desiredd();
  }

  var totalPrice = (current_division + desired_division);

  document.getElementById('prices').value = totalPrice;
  document.getElementById("prices").readOnly = true;


}

document.getElementById('divboost').addEventListener('change', function() {
  total();
})
<form id="divboost" name="priceCalc" action="">
  <br/>
  <select id="CRANK1"> Current Rank
        <option value="0">Bronze</option>
        <option value="1">Silver</option>
        <option value="2">Gold</option>
        <option value="3">Platinum</option>
        <option value="4">Diamond</option>
    </select>
  <br>
  <br/>
  <select id="CRANK2"> Current Divison
        <option value="5">Division 5</option>
        <option value="6">Division 4</option>
        <option value="7">Division 3</option>
        <option value="8">Division 2</option>
        <option value="9">Division 1</option>
    </select>
  <br>
  <br>
  <br/>
  <br/>
  <select id="DRANK1"> Desired Rank
        <option value="0">Bronze</option>
        <option value="1">Silver</option>
        <option value="2">Gold</option>
        <option value="3">Platinum</option>
        <option value="4">Ddiamond</option>
    </select>
  <br>
  <br/>
  <select id="DRANK2"> Desired Divison
        <option value="5">Division 5</option>
        <option value="6">Division 4</option>
        <option value="7">Division 3</option>
        <option value="8">Division 2</option>
        <option value="9">Division 1</option>
    </select>
  <br>
  <br>
  <input type="text" id="prices">
  <br/>
  <br>
</form>
Ben
  • 15
  • 2

2 Answers2

0

As you can see here: Entire form onChange , with pure JS you can't add a change listener to an entire form at once. You need to add a listener to each element inside it that you want to change. The code below shows how.

Also, I don't know the values for each "Color" (bronze, silver, etc...), so I invented the values, increasing each one by 2... The math used is: The "Color" value is the multiplier, and the "Division" value is the real value. So,

Bronze (multiplier 2) * Division 4 (value 2) equals = $ 6

The values and numbers you should adjust accordling to your needs, but I think the logic here will help you.
Probably you will need more than just set value to the options, it woulb be better to store the values in an object or array and then get the values from there, it would help in more complex math needs.

See the code below, clicking to show Snippet, and tell me if this helps you.

var current_division,
    desired_division;
    
    
function current1() {
  var Amt = document.priceCalc.CRANK1;
  var Qty = document.priceCalc.CRANK2;
  return parseInt(Qty.value) * parseFloat(Amt.value);
}

function desiredd() {
  var Amt = document.priceCalc.DRANK1;
  var Qty = document.priceCalc.DRANK2;
  return price = parseInt(Qty.value) * parseFloat(Amt.value);

}

function total() {
  if (isNaN(current1())) {
    current_division = 0;
  } else {
    current_division = current1();
  }

  if (isNaN(desiredd())) {
    desired_division = 0;
  } else {
    desired_division = desiredd();
  }

  var totalPrice = (current_division + desired_division);

  document.getElementById('prices').value = totalPrice;
  document.getElementById("prices").readOnly = true;
}

var changers = document.getElementsByClassName('changer');
for (var i =0; i < changers.length; i++){
  var changer = changers[i];
  changer.addEventListener('change', function() {
    total();
  })
}
<form id="divboost" name="priceCalc" action="">
  <br/>
  <select id="CRANK1" class='changer'> Current Rank
        <option value="2">Bronze</option>
        <option value="4">Silver</option>
        <option value="6">Gold</option>
        <option value="8">Platinum</option>
        <option value="10">Diamond</option>
    </select>
  <br>
  <br/>
  <select id="CRANK2" class='changer'> Current Divison
        <option value="0">Division 5</option>
        <option value="1">Division 4</option>
        <option value="2">Division 3</option>
        <option value="3">Division 2</option>
        <option value="4">Division 1</option>
    </select>
  <br>
  <br>
  <br/>
  <br/>
  <select id="DRANK1" class='changer'> Desired Rank
        <option value="2">Bronze</option>
        <option value="4">Silver</option>
        <option value="6">Gold</option>
        <option value="8">Platinum</option>
        <option value="10">Diamond</option>
    </select>
  <br>
  <br/>
  <select id="DRANK2" class='changer'> Desired Divison
        <option value="0">Division 5</option>
        <option value="1">Division 4</option>
        <option value="2">Division 3</option>
        <option value="3">Division 2</option>
        <option value="4">Division 1</option>
    </select>
  <br>
  <br>
  $ <input type="text" id="prices">
  <br/>
  <br>
</form>
Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
0

I understand that you need to follow fixed prices (it would not be a simple math equation).

For that reason I recommend you use an array on your code to hold the values for all prices. You would need to update the javascript array to represent the correct values.

Dividing prices on ranks/divisions is pointless. Instead of having two separate lists, you can merge two in one: B5, B4, B3, B2, B1, S5, S4, ... (where B=Bronze and S=Silver).

So you have one single list of prices. What you need to do is get what index at the array is the current rank + division, and what index at the array is the desired rank + division.

When you have those two values, you just need to sum all values from the current index to the desired index, thus getting the accumulated values.

Also I recommend warning the user if they select a less rank/division than they currently are, or otherwise the price would be negative (having a surprising economic impact).

I added the first 3 ranks, you can do the remaining 2. From an UX point of view, I honestly recommend using a single select, since there are not too many values, and it would mean less clicks for the user. If you want to go that route, let me know and I will update the script.

Show warning if user selected invalid rank/division (simpler)

var current_division,
    desired_division;

// These are the flattened prices for all divisions.
// First is bronze div5, second is bronze div4, bronze div3,
// bronze div2, bronze div1, silver div 5, etc.
// You would need to add the remaining ranks and update the prices.
var prices = [
00,02,04,06,08,
10,12,14,16,18,
20,22,24,26,28
];
    
    
function getCurrentIndex() {
  return (+document.getElementById("CRANK1").value + 
    +document.getElementById("CRANK2").value);
}

function getDesiredIndex() {
  return (+document.getElementById("DRANK1").value + 
    +document.getElementById("DRANK2").value);
}

function total() {
  var currentIndex = getCurrentIndex();
  var desiredIndex = getDesiredIndex();
  
  // If desiredIndex is greater than currentIndex, warn the user
  // that they can't go from high to low!
  if (desiredIndex < currentIndex) {
    document.getElementById('prices').value = "You can't rank backwards";
    return;
  }
  
  // Now you need to start summing the prices from currentIndex
  // to desiredIndex.
  
  var accumulatedPrice = 0;
  for(var i = currentIndex; i <= desiredIndex; i++) {
    accumulatedPrice += prices[i];
  }
  
  document.getElementById('prices').value = accumulatedPrice;
  document.getElementById("prices").readOnly = true;


}

document.getElementById('divboost').addEventListener('change', function() {
  total();
})
<form id="divboost" name="priceCalc" action="">
  <br/>
  <select id="CRANK1"> Current Rank
        <option value="0">Bronze</option>
        <option value="5">Silver</option>
        <option value="10">Gold</option>
    </select>
  <br>
  <br/>
  <select id="CRANK2"> Current Divison
        <option value="0">Division 5</option>
        <option value="1">Division 4</option>
        <option value="2">Division 3</option>
        <option value="3">Division 2</option>
        <option value="4">Division 1</option>
    </select>
  <br>
  <br>
  <br/>
  <br/>
  <select id="DRANK1"> Desired Rank
        <option value="0">Bronze</option>
        <option value="5">Silver</option>
        <option value="10">Gold</option>
    </select>
  <br>
  <br/>
  <select id="DRANK2"> Desired Divison
        <option value="0">Division 5</option>
        <option value="1">Division 4</option>
        <option value="2">Division 3</option>
        <option value="3">Division 2</option>
        <option value="4">Division 1</option>
    </select>
  <br>
  <br>
  <input type="text" id="prices">
  <br/>
  <br>
</form>

Hide invalid options (more complex)

var current_division,
    desired_division;

// These are the flattened prices for all divisions.
// First is bronze div5, second is bronze div4, bronze div3,
// bronze div2, bronze div1, silver div 5, etc.
// You would need to add the remaining ranks and update the prices.
var prices = [
00,02,04,06,08,
10,12,14,16,18,
20,22,24,26,28
];
    
    
function getIndex(rankNode, divisionNode) {
  return +rankNode.value + +divisionNode.value;
}

// show: can be a boolean or a function filter
function showHTMLCollection(htmlCollection, show) {
  if (!htmlCollection || htmlCollection.length === 0) return;
  show = typeof show === "undefined" ? true : show;
  for (var i = 0; i < htmlCollection.length; i++) {
      var computedShow = typeof show === "function" ? show(htmlCollection[i]) : show;
      htmlCollection[i].disabled = !computedShow;
      htmlCollection[i].style.display = computedShow ? "" : "none";
  }
}

function validateSelectValue(selectNode) {
  // If <select> has selected a disabled <option>, set to first valid value
  var selectedOptionNode = selectNode.querySelector("option[value='" + selectNode.value + "']");
  if (selectNode.value == "" || selectedOptionNode.disabled) {
    for (var i = 0; i < selectNode.children.length; i++) {
      if (!selectNode.children[i].disabled) {
        selectNode.value = selectNode.children[i].value;
        return;
      }
    }
    // There's no more valid values on the list, set to empty
    selectNode.value = "";
  }
}

function total() {
  var currentRankNode = document.getElementById("CRANK1");
  var currentDivisionNode = document.getElementById("CRANK2");
  var currentIndex = getIndex(currentRankNode, currentDivisionNode);
  
  var desiredRankNode = document.getElementById("DRANK1");
  var desiredDivisionNode = document.getElementById("DRANK2");
  var desiredIndex = getIndex(desiredRankNode, desiredDivisionNode);
  
  var desiredRankChildren = desiredRankNode.children;
  
  // Hide ranks based on filter
  showHTMLCollection(desiredRankChildren, function(option) {
    // Show only desired ranks greater than the current rank,
    // or if same rank, we are not on the last division
    // otherwise we can't keep ranking
    return (option.value > +currentRankNode.value ||
    (option.value == +currentRankNode.value && +currentDivisionNode.value < 4));
  });
  
  // Make sure that the desired ranks select contains valid value
  validateSelectValue(desiredRankNode);
  
  var desiredDivisionChildren = desiredDivisionNode.children;
  
    // Hide divisions based on filter
  showHTMLCollection(desiredDivisionChildren, function(option) {
    // If greater rank, show all divisions. If same rank,
    // show only desired divisions greater than the current divisions
    return (+desiredRankNode.value > +currentRankNode.value ||
    (+desiredRankNode.value == +currentRankNode.value && option.value > +currentDivisionNode.value));
  });
  
  // Make sure that the desired ranks select contains valid value
  validateSelectValue(desiredDivisionNode);
  
  // Now you need to start summing the prices from currentIndex
  // to desiredIndex.
  
  var accumulatedPrice = 0;
  for(var i = currentIndex; i <= desiredIndex; i++) {
    accumulatedPrice += prices[i];
  }
  
  document.getElementById('prices').value = accumulatedPrice;
  document.getElementById("prices").readOnly = true;


}

document.getElementById('divboost').addEventListener('change', function() {
  total();
})
<form id="divboost" name="priceCalc" action="">
  <br/>
  <select id="CRANK1"> Current Rank
        <option value="0">Bronze</option>
        <option value="5">Silver</option>
        <option value="10">Gold</option>
    </select>
  <br>
  <br/>
  <select id="CRANK2"> Current Divison
        <option value="0">Division 5</option>
        <option value="1">Division 4</option>
        <option value="2">Division 3</option>
        <option value="3">Division 2</option>
        <option value="4">Division 1</option>
    </select>
  <br>
  <br>
  <br/>
  <br/>
  <select id="DRANK1"> Desired Rank
        <option value="0">Bronze</option>
        <option value="5">Silver</option>
        <option value="10">Gold</option>
    </select>
  <br>
  <br/>
  <select id="DRANK2"> Desired Divison
        <option value="0" disabled style="display: none">Division 5</option>
        <option value="1" selected>Division 4</option>
        <option value="2">Division 3</option>
        <option value="3">Division 2</option>
        <option value="4">Division 1</option>
    </select>
  <br>
  <br>
  <input type="text" id="prices">
  <br/>
  <br>
</form>
Jorjon
  • 5,316
  • 1
  • 41
  • 58
  • Thank you so much, got it all working. Just a thought, instead of having text show up when desiredIndex < currentIndex, is there a way to hide lower ranks/divisions when finished selecting current? – Ben Apr 19 '18 at 17:48
  • @Ben Yes it's possible, when I find time I will update the answer. It's courtesy to _upvote_ any answer you find valuable. – Jorjon Apr 19 '18 at 18:19
  • I'm still new around here so i get the message "Thanks for the feedback! Votes cast by those with less than 15 reputation are recorded, but do not change the publicly displayed post score." I upvoted you, don't worry :) – Ben Apr 19 '18 at 19:02
  • Added second option to hide invalid rank/divisions – Jorjon Apr 22 '18 at 09:25