Event Handling
The following demo upon triggering the "input"
event*, on the <input type="number">
will change the <select>
<option>
according to the value of <input type="number">
being within a dynamic range. Although the demo has hard-coded values for data-min
and data-max
, the callback function cbd()
can handle any valid values set dynamically for each data-min/max
pair assigned to each <option>
.
* (the advantage of "input"
event over "change"
event is that it is happens instantly)
BTW never use an on-event attribute:
Example of what NOT to do for event handling with jQuery or JavaScript
<button onclick="functionName()">LAME</button>
...
function functionName(event) {...
When using jQuery, always use the proper method (ex. .click()
) or delegate events with the .on()
method (I highly recommend using the latter 99% of the time.)
Example of the most effective way of event handling with jQuery
<button class='btn'>NOT LAME</button>
...
$('.btn').on('click', functionName)
function functionName(event) {...
The demo is commented extensively and there are references provided as well.
Demo
// Delegate input#cdbData to the input event -- callback is cdb()
$(function() {
$('#cbdData').on('input', cbd);
});
// Callback function/Event handler passes Event Object by default
function cbd(event) {
/*
Dereferenced jQuery Object $('#cbdRate') to DOM Object
NOTE: Plain JavaScript equivelant would be:
const select = document.getElementById('cdbRate');
or
const select = document.querySelector('#cdbRate');
*/
const select = $('#cbdRate')[0];
// Collect all select#cdbRate option into an Array
const rates = [...select.options];
/*
Store the value of input#cdbData as a real Number in a variable
IMPORTANT NOTE: input#cdbData is $(this)
*/
let float = parseFloat($(this).val());
/*
Ensure that integer values are suffixed with ".0"
(this is just for aesthetics and is not required)
*/
$(this).val(float.toFixed(1));
/*
IF input#cdbData value is :out-of-range...
add .out class and remove .in class
OTHERWISE...
do vice versa of the above actions
(this is just for aesthetics and is not required)
*/
if ($(this).is(':out-of-range')) {
$(this).addClass('out').removeClass('in');
} else {
$(this).addClass('in').removeClass('out');
}
/*
.flatMap() method (a combo of .map() and .flat() methods), will run a
function over each element within a given array and will return a flattened
array of results. NOTE: the callback function returns an Array of an Array --
so the final return will be an Array of Arrays
(aka two dimensional array, aka data-table)
On each select#cdbRate option...
Get the value of data-min convert it into a real Number and add it to the
minMax sub-Array[0]
Then do likewise for data-max and minMax sub-Array[1]
Final returned minMax Array has the following pattern:
minMax = [['', ''], [data-min, data-max], [data-min, data-max], [data-min, data-max]];
Each sub-Array represents the min/max values of an <option>
Use the .data() jQuery method to set/get data-* attributes
*/
let minMax = rates.flatMap((opt, idx) => {
return idx === 0 ? [
["", ""]
] : [
[Number($(opt).data('min')), Number($(opt).data('max'))]
]
});
// Get length of minMax Array
let size = minMax.length;
// Get the least and the greatest values of minMax Array
let min = minMax[1][0];
let max = minMax[size - 1][1];
// Assign min and max values to input#cbdData
this.min = min;
this.max = max;
/*
Iterate through rates Array...
IF `float` is greater OR equal to current value of minMax sub-Array[0]
AND...
IF `float` is less OR equal to current value of minMax sub-Array[1]...
then select the current <option>
OR IF `float` is not a Number OR `float` is greater than the last value of
minMax Array[1]...
then select <option> at index 0
IMPORTANT NOTE: The dereferenced jQuery Object `select` must be used because
the Plain JavaScript property .selectedIndex and .selected are not recognized
by jQuery
*/
for (let [index, option] of rates.entries()) {
if (float >= minMax[index][0] && float <= minMax[index][1]) {
option.selected = true;
} else if (Number.isNaN(float) || float > max) {
select.selectedIndex = 0;
}
}
// Uncomment the comment below to review the log of minMax Array
// log(minMax);
// Stop event bubbling and terminate function
return false;
}
// Optional utility function (not required)
function log(data) {
return console.log(JSON.stringify(data));
}
:root {
font: 400 3vw/6vh Consolas
}
.form-control {
display: inline-block;
font: inherit;
font-size: 1rem
}
#cbdData {
width: 6ch;
text-align: center;
}
.in {
background: initial;
}
.out {
background: tomato;
}
<input id="cbdData" name="cbdData" class="form-control" type="number" step="0.1">
<select id="cbdRate" name="cbdRate" class="form-control">
<option value="" default>-----</option>
<option data-min="0.0" data-max="0.0" value='{D6C3B40F-9559-473A-8B24-44A911A82D52}'>CBD 0</option>
<option data-min="0.1" data-max="1.9" value='{4FD86F65-74BA-4F10-9D5F-57281ECFC76A}'>CBD 1</option>
<option data-min="2.0" data-max="2.9" value='{3AC0F33C-D48E-4C10-B64A-B5473AF8DB98}'>CBD 2</option>
</select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
References
Delegating events with jQuery .on()
method
Dereferencing jQuery Object to DOM Object
Creating or cloning an array via spread operator
$(this)
.flatMap()
Destructuring arrays with .entries()
and a for...of
loop
.selectedIndex
and .selected
properties and .options
HTML Collection