I created a length converter just like the one on google including all the units. I did it using the if/else statement and it works perfectly but my code is very long (about 450 lines of code). is there another way of doing the same thing?
below is only one unit (meter to the rest of the units)
Thank you
const input = document.getElementById("input");
const inputType = document.getElementById("inputType");
const output = document.getElementById("output");
const outputType = document.getElementById("outputType");
let inputResult, outputResult;
const finalResult = () => {
inputResult = inputType.value;
outputResult = outputType.value;
// Meter
if (inputResult === "m" && outputResult === "Cm") {
//Meter to Centimeter
output.value = Number(input.value) * 100;
} else if (inputResult === "m" && outputResult === "Mm") {
//Meter to Millimeter
output.value = Number(input.value) * 1000;
} else if (inputResult === "m" && outputResult === "Km") {
//Meter to kilometer
output.value = Number(input.value) / 1000;
} else if (inputResult === "m" && outputResult === "mm") {
//Meter to Micrometer
output.value = Number(input.value) * 1e6;
} else if (inputResult === "m" && outputResult === "Nm") {
//Meter to Nanometer
output.value = Number(input.value) * 1e9;
} else if (inputResult === "m" && outputResult === "Mi") {
//Meter to Mile
output.value = Number(input.value) / 1609;
} else if (inputResult === "m" && outputResult === "Y") {
//Meter to Yard
output.value = Number(input.value) * 1.094;
} else if (inputResult === "m" && outputResult === "f") {
//Meter to Foot
output.value = Number(input.value) * 3.281;
} else if (inputResult === "m" && outputResult === "In") {
//Meter to Inch
output.value = Number(input.value) * 39.37;
} else if (inputResult === "m" && outputResult === "NM") {
//Meter to Nautical Mile
output.value = Number(input.value) / 1852;
} else if (inputResult === "m" && outputResult === "m") {
//Meter to Meter
output.value = input.value;
}
CodePudding user response:
Some things take a lot of code.. but yes you can make it shorter
The snippet below is compared_input=input*(measurement/compared_measurement)
const lengthTypes={ //a record of every length type with values that they are relative to each other
Nm:1, //the smallest unit in the calculator, thus everything else is a COUNT of Nm
mm:1000, //one micrometre is 1000 nanometres
Mm:1e6, //one millimetre is 1 million nanometres
Cm:1e7, //one cm is 10 million nanometres
In:2.54e7, //one inch is 25.4 million nanometres
f:3.048e8, //one foot is 304.8 million nanometres
Y:9.144e8, //one yard is 914.4 million nanometres
m:1e9, //one metre is 1 billion nanometers
Km:1e12, //one kilometre is 1 trillion nanometres
Mi:1.609e12, //one mile is 1.609 trillion nanometres
NM:1.852e12, //one nautical mile is trillion nanometres
}
//1 for the bar on the left, 2 for the bar on the right
const input1 = document.getElementById("input1");
const inputType1 = document.getElementById("inputType1");
const input2 = document.getElementById("input2");
const inputType2 = document.getElementById("inputType2");
function handleChange(e){
let type1=inputType1.value, type2=inputType2.value
if([input1,inputType1,inputType2].includes(e.target||e.path[0])){
//left hand side changed by human(so set right side)
const n=parseInt(input1.value)
if(isNaN(n)){return null}
input2.value=n*(lengthTypes[type1]/lengthTypes[type2])
}
else{
//right hand side changed by human(so set left side)
const n=parseInt(input2.value)
if(isNaN(n)){return null}
input1.value=n*(lengthTypes[type2]/lengthTypes[type1])
}
}
input1.addEventListener('change',handleChange)
input2.addEventListener('change',handleChange)
inputType1.addEventListener('change',handleChange)
inputType2.addEventListener('change',handleChange)
.card{
display:table;
height:50%;
width:80%;
background-color:lightblue;
}
.bar{
float:left;
width:40%;
height:90%;
margin:10px;
background-color:teal;
}
input{
width:80%;
}
select{
width:85%;
}
<div >
<div >
<input type="number" id="input1" />
<select id="inputType1">
<option value="Nm">Nanometre</option>
<option value="mm">Micrometre</option>
<option value="Mm">Millimetre</option>
<option value="Cm">Centimetre</option>
<option value="In">Inch</option>
<option value="f">Foot</option>
<option value="Y">Yard</option>
<option value="m">Metre</option>
<option value="Km">Kilometre</option>
<option value="Mi">Mile</option>
<option value="NM">Nautical Mile</option>
</select>
</div>
<div >
<input type="number" id="input2" />
<select id="inputType2">
<option value="Nm">Nanometre</option>
<option value="mm">Micrometre</option>
<option value="Mm">Millimetre</option>
<option value="Cm">Centimetre</option>
<option value="In">Inch</option>
<option value="f">Foot</option>
<option value="Y">Yard</option>
<option value="m">Metre</option>
<option value="Km">Kilometre</option>
<option value="Mi">Mile</option>
<option value="NM">Nautical Mile</option>
</select>
</div>
</div>
CodePudding user response:
If you wanted to make it shorter you could set up a sort of anchor and convert off of that. The npm library units-converter does this. This file you would want is the length units
If you are going to the anchor you multiply by the to anchor unit and if you are going away from the anchor you divide.
Example:
Input: 12 km
Output: Centimeters
Anchor: Meter
12 km * 1000 = 12000 meters
12000 meters / (1/100) = 1200000 cm
CodePudding user response:
Detials commented in example
/**
* @desc - Simple multiplication and division
* @param {number} a - Operand
* @param {number} z - Operand
* @param {string} o - Operator
* @return {number} Product or quotient of a & z
*/
const divPro = (a, z, o) =>
o === '*' ? a * z :
o === '/' ? a / z :
o === '-*' ? a / z :
o === '-/' ? a * z : 0;
// Bind input event to <form>
document.forms[0].oninput = convert;
// Event handler passes Event Object by default
function convert(e) {
// Object of constants and operators
const M = {
x: [0, ''],
m: [1, '/'],
cm: [100, '/'],
mm: [1000, '/'],
km: [1000, '*'],
um: [1e6, '/'],
nm: [1e9, '/'],
mi: [1609, '*'],
yd: [1.094, '/'],
ft: [3.281, '/'],
in: [39.37, '/'],
nmi: [1852, '*']
};
// Reference all form controls
const fc = this.elements;
// Get the number from <input>
let amtA = parseFloat(fc.amountA.value) || 0;
// Get the value of first <select> - A
let a = fc.unitA.value || 'x';
// Get the number associated with first <select> value - B
let uniA = parseFloat(M[a][0]);
// Get the operator associated with first <select> value - C
let oprA = M[a][1];
// A
let z = fc.unitZ.value || 'x';
// B second <select>
let uniZ = parseFloat(M[z][0]);
// C second <select>
let oprZ = M[z][1];
// Determine the value in meters
let A = divPro(amtA, uniA, oprA) || 0;
// Determine the value from meters to selected unit
let Z = divPro(A, uniZ, '-' oprZ) || 0;
// Display result in <output>
fc.amountZ.value = Z || 0;
}
html {
font: 300 2ch/1 'Segoe UI'
}
input,
select {
font: inherit;
}
#amountA,
#amountZ {
width: 8rem;
font-family: Consolas;
text-align: right;
}
#amountZ {
display: inline-block;
min-width: max-content;
}
<form>
<input id='amountA' type='number' min='0' step='any' value='0'> 
<select id='unitA'>
<option value='x'>From</option>
<option value='m'>Meter</option>
<option value='cm'>Centimeter</option>
<option value='mm'>Millimeter</option>
<option value='km'>Kilometer</option>
<option value='um'>Micrometer</option>
<option value='nm'>Nanometer</option>
<option value='mi'>Mile</option>
<option value='yd'>Yard</option>
<option value='ft'>Foot</option>
<option value='in'>Inch</option>
<option value='nmi'>Nautical Mile</option>
</select><br>
<output id='amountZ' value='0'></output>
<select id='unitZ'>
<option value='x'>To</option>
<option value='m'>Meter</option>
<option value='cm'>Centimeter</option>
<option value='mm'>Millimeter</option>
<option value='km'>Kilometer</option>
<option value='um'>Micrometer</option>
<option value='nm'>Nanometer</option>
<option value='mi'>Mile</option>
<option value='yd'>Yard</option>
<option value='ft'>Foot</option>
<option value='in'>Inch</option>
<option value='nmi'>Nautical Mile</option>
</select>
</form>