javascript - 通过下拉列表和用户输入和 javascript 将英制值转换为公制

标签 javascript

我有这些变量:

  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,它可以在用户输入时立即更改值。理想情况下,它还会根据用户在两个不同的下拉列表中所做的选择来更改值:

<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..
  }

我猜这是几个问题,但只是一些提示或评论会非常有帮助。

最佳答案

是这样的吗?

// 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>&nbsp;=&nbsp;</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>&nbsp;=&nbsp;</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>

关于javascript - 通过下拉列表和用户输入和 javascript 将英制值转换为公制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53085716/

相关文章:

javascript - 获取 Meteor 中集合的索引列表

javascript - 函数与对象文字表示法 - 有区别吗?

javascript - JQuery 函数未定义

javascript - 导航栏跳转问题

javascript - 如何使用 jenkins 部署 javascript 项目?

javascript - 当鼠标移动到带有jquery的文本上时显示图片?

Javascript函数在调用之前执行

javascript - Phonegap 屏幕尺寸 (android)

javascript - 使用 BabelJS 导出默认变量

javascript - 在代码隐藏(c#)中多次执行javascript函数