charliehorse55
charliehorse55

Reputation: 1990

javascript engineering input library

I'm writing a web based front end for an engineering simulation. The back end only accepts values in non-prefixed SI units, such as meters or watts. However it would be preferable to allow the user to enter values in any unit they wish. For example, if you needed to enter a distance, you could enter:

15 inches
3.1 meter
1.4 km

but values such as:

12 seconds
5 pounds
147 watts

would be rejected. I first tried using js-quantities, but it doesn't parse derived units in the most intuitive way. It requires a space to be placed between each multiplied unit. For example, to enter an amount of charge in amp hours, 100 Ah is invalid, but 100 A h is acceptable. Additionally, js-quantities does not support units of torque or temperature (only temperature difference, you can't convert Fahrenheit to Celsius for example)

I then tried to use the google calculator API to do unit conversions, but it produces hard to parse results for small numbers:

Convert 5 nm to meters

request:

http://www.google.com/ig/calculator?hl=en&q=5%20nm=?m

response:

{lhs: "5 nanometers",rhs: "5.0 \x26#215; 10\x3csup\x3e-9\x3c/sup\x3e meters",error: "",icc: false}

Upvotes: 4

Views: 490

Answers (3)

Mike H.
Mike H.

Reputation: 1751

Have you looked at mathjs?

http://mathjs.org/

It doesn't have derived units yet (I don't believe) but they are working on it. Other than that it's probably the closest thing to what you want.

If you need more functionality specific to your industry of engineering, you'll need to extend a library at some point.

Upvotes: 1

vinaut
vinaut

Reputation: 2446

The Google calculator output doesn't seem too difficult to parse.

I would do something like this:

//Parse JSON output to JS variables
    ret = JSON.parse(JSON.stringify({lhs: "5 nanometers",rhs: "5.0 \x26#215; 10\x3csup\x3e-9\x3c/sup\x3e meters",error: "",icc: false} ));

  //ret = Object {lhs: "5 nanometers", rhs: "5.0 &#215; 10<sup>-9</sup> meters", error: "", icc: false}
  var lhs = new Object();
  //Check if lhs has exp notation 
  if (ret.lhs.search("&#215; ")!==-1) {
  //If so, conversion is a bit harder...but not much
  temp = ret.lhs.split("&#215; ");  
  lhs.base = temp[0]

  temp = temp[1].split("<sup>")[1].split("</sup>");
  lhs.exp = temp[0];
  lhs.unit = temp[1];
  lhs.num = parseFloat(lhs.base)*Math.pow(10,parseFloat(lhs.exp));
} else {
  //If no, piece of cake
  temp = ret.lhs.split(" ");  
  lhs.num = parseFloat(temp[0]);
  lhs.unit = temp[1];
}

//Exactly the same for rhs
var rhs = new Object();    
if (ret.rhs.search("&#215; ")!==-1) {

  temp = ret.rhs.split("&#215; ");  
  rhs.base = temp[0]

  temp = temp[1].split("<sup>")[1].split("</sup>");
  rhs.exp = temp[0];
  rhs.unit = temp[1];
  rhs.num = parseFloat(rhs.base)*Math.pow(10,parseFloat(rhs.exp));

} else {
  temp = ret.lhs.split(" ");  
  lhs.num = parseFloat(temp[0]);
  lhs.unit = temp[1];
}

console.log("Converted",lhs.num,lhs.unit,"to",rhs.num,rhs.unit);

Output : Converted 5 nanometers to 5e-9 meters

Since you now have both lhs and rhs as numeric javascript variables and their units as strings, you can format/process them as much as you like.

Upvotes: 1

Rickard Liljeberg
Rickard Liljeberg

Reputation: 1018

It seems to me that modifying js-quantities would be fairly easy.

You simply edit the function parse(val) function. You try to parse and after failing you simply insert spaces as required by very simple ruleset. You go trough the string from left to right and identify units and split the string.

However I would probably go with another solution where you split it already when the user inputs it (by the same kind of rules). That way when the user inputs a value it can show "using amp hours" for Ah and the user can see that everything is the way he meant for it to be. That way you can offer the user to chose from a list (or more advanced builder) if it is not what he meant.

Upvotes: 2

Related Questions