我有这些变量:
var imperialConverterTable = {
inch: 25.4,
foot: 12*25.4,
yard: 3*12*25.4,
mile: 1760*3*12*25.4
};
var metricConverterTable = {
millimeter: 1,
centimeter: 10,
decimeter: 100,
meter: 1000,
kilometer: 1E6,
mil: 1E7
};
我想设置一个JavaScript,该JavaScript可在用户输入时立即更改值。理想情况下,它还会根据用户在两个不同的下拉列表中做出的选择来更改值:
<input type="number" id="lengthVal" value=«10»>
<select id="imperialBenevning">
<option id="inch" type="number" oninput="imperialConverterTable(this.id,this.value)" onchange="imperialConverterTable(this.id,this.value)">inch</option>
<option id="foot" type="number" oninput="imperialConverterTable(this.id,this.value)" onchange="imperialConverterTable(this.id,this.value)">foot</option>
<option id="yard" type="number" oninput="imperialConverterTable(this.id,this.value)" onchange="imperialConverterTable(this.id,this.value)">yard</option>
<option id="mile" type="number" oninput="imperialConverterTable(this.id,this.value)" onchange="imperialConverterTable(this.id,this.value)">mile</option>
</select>
<label> = </label>
<select id="metricBenevning">
// Some kind of output-field here?
<option id="millimeter" type="number" oninput="metricConverterTable(this.id,this.value)" onchange="metricConverterTable(this.id,this.value)">millimeter</option>
<option id="centimeter" type="number" oninput="metricConverterTable(this.id,this.value)" onchange="metricConverterTable(this.id,this.value)">centimeter</option>
<option id="decimeter" type="number" oninput="metricConverterTable(this.id,this.value)" onchange="metricConverterTable(this.id,this.value)">decimeter</option>
<option id="meter" type="number" oninput="metricConverterTable(this.id,this.value)" onchange="metricConverterTable(this.id,this.value)">meter</option>
<option id="kilometer" type="number" oninput="metricConverterTable(this.id,this.value)" onchange="metricConverterTable(this.id,this.value)">kilometer</option>
<option id="mil" type="number" oninput="metricConverterTable(this.id,this.value)" onchange="metricConverterTable(this.id,this.value)">mil</option>
</select>
我试图制作这样的if函数:
function lengthVal(source,valNum) {
valNum = parseFloat(valNum);
var foot = document.getElementById("foot");
var inch = document.getElementById("inch");
var yard = document.getElementById("yard");
var mile = document.getElementById("mile");
var centimeter = document.getElementById("centimeter");
var decimeter = document.getElementById("decimeter");
var meter = document.getElementById("meter");
var kilometer = document.getElementById("kilometer");
var mil = document.getElementById("mil");
if (source=="foot") {
meter.value=(valNum/3.2808).toFixed(2);
inch.value=(valNum*12).toFixed(2);
//and so on for all the values, but no luck so far..
}
我想一下这几个问题,但是只有一些提示或评论会很有帮助。
答案 0 :(得分:1)
像这样吗?
// JS' Numeric system sometimes has some issues that can not be properly represented in binary format
const fixFloat = value => Math.round(value * 1e10) / 1e10;
// a simple definition of the units, imo. very readable
// I made the meter = 1 since in the metric system
// all other lengths are derived from that. It's literally in the name
// milli-meter == one thousandth meter
// this only affects the values, but not the conversions
const meter = 1,
decimeter = meter / 10,
centimeter = meter / 100,
millimeter = meter / 1000,
kilometer = meter * 1000,
mil = 10 * kilometer, // Scandinavian mile, had to look this one up, imo. it's not common
inch = 25.4 * millimeter,
foot = 12 * inch,
yard = 3 * foot,
mile = 1760 * yard;
// Since I have them defined now,
// I want to create the options for the prepared select-boxes from these values
let options = [
["Imperial", {
inch,
foot,
yard,
mile
}],
["Metric", {
millimeter,
centimeter,
decimeter,
meter,
kilometer,
mil
}]
].map(([label, units]) => `
<optgroup label="${label}">
${ Object.entries(units)
.sort((a,b) => a[1] - b[1])
.map(([unit, value]) => `<option value="${fixFloat(value)}">${unit}</option>`)
.join("\n ")
}
</optgroup>`)
.join("")
.trim();
console.log(options);
[...document.querySelectorAll('#aa, #bb')].forEach(select => {
select.innerHTML = options;
});
//now let's bring some interactivity to this:
function convert(value, fromScale, toScale) {
return fixFloat(value * fromScale / toScale);
}
function update(e) {
// deciding in wich direction to compute, based on what field has been changed
switch (e.target.id) {
// -->
case "a":
case "bb":
document.querySelector("#b").value = convert(
document.querySelector("#a").value,
document.querySelector("#aa").value,
document.querySelector("#bb").value
);
break;
// <--
case "b":
case "aa":
document.querySelector("#a").value = convert(
document.querySelector("#b").value,
document.querySelector("#bb").value,
document.querySelector("#aa").value
);
break;
}
}
// add the event-listener to the input and select-boxes
[...document.querySelectorAll('select, input')].forEach(elm => {
elm.oninput = elm.onchange = update;
});
<input type="number" id="a" value="1">
<select id="aa"></select>
<span> = </span>
<input type="number" id="b" value="1" >
<select id="bb"></select>
由于该代码的上半部分仅用于定义创建<option>
的单位,因此您可以直接在<select>
框中编写生成的标记,而JS只需要处理计算即可:
// JS' Numeric system has some issues with numbers that
// can not be properly represented in binary format:
// check: console.log(0.1 * 0.1);
const fixFloat = value => Math.round(value * 1e10) / 1e10;
function convert(value, fromScale, toScale) {
return fixFloat(value * fromScale / toScale);
}
function update(e) {
// deciding in wich direction to compute, based on what field has been changed
switch (e.target.id) {
// -->
case "a":
case "bb":
document.querySelector("#b").value = convert(
document.querySelector("#a").value,
document.querySelector("#aa").value,
document.querySelector("#bb").value
);
break;
// <--
case "b":
case "aa":
document.querySelector("#a").value = convert(
document.querySelector("#b").value,
document.querySelector("#bb").value,
document.querySelector("#aa").value
);
break;
}
}
// add the event-listener to the input and select-boxes
[...document.querySelectorAll('select, input')].forEach(elm => {
elm.oninput = elm.onchange = update;
});
<input type="number" id="a" value="1">
<select id="aa">
<!--
the unit for these values is meter
1 inch === 0.0254 meter
-->
<optgroup label="Imperial">
<option value="0.0254">inch</option>
<option value="0.3048">foot</option>
<option value="0.9144">yard</option>
<option value="1609.344">mile</option>
</optgroup>
<optgroup label="Metric">
<option value="0.001">millimeter</option>
<option value="0.01">centimeter</option>
<option value="0.1">decimeter</option>
<option value="1">meter</option>
<option value="1000">kilometer</option>
<option value="10000">mil</option>
</optgroup>
</select>
<span> = </span>
<input type="number" id="b" value="1">
<select id="bb">
<optgroup label="Imperial">
<option value="0.0254">inch</option>
<option value="0.3048">foot</option>
<option value="0.9144">yard</option>
<option value="1609.344">mile</option>
</optgroup>
<optgroup label="Metric">
<option value="0.001">millimeter</option>
<option value="0.01">centimeter</option>
<option value="0.1">decimeter</option>
<option value="1">meter</option>
<option value="1000">kilometer</option>
<option value="10000">mil</option>
</optgroup>
</select>