What is the best/most elegant way to abstract out the conversion of units of measures in the client, based on a user-preferred unit of measure setting?
For example,
I'll just leave this here ...
;;if (!window.hasOwnProperty('convertImperialMetric')) {
function convertImperialMetric () {
var metrics = convertImperialMetric.metrics,
imperials = convertImperialMetric.imperials,
args = arguments,
conversionTypes = { imperial: 'imperial', metric: 'metric' },
toFixed = false, toFixedX = 2,
intX, typImp, typMet, conType = 'metric',
$ret;
conversionTypes.i = conversionTypes.imp = conversionTypes.imperial;
conversionTypes.m = conversionTypes.met = conversionTypes.metric;
function setVarz(c) {
for (i in c) {
var a = c[i];
switch (typeof a) {
case "boolean":
toFixed = a;
break;
case "number":
void 0 == intX ? intX = a : toFixedX = a;
break;
case "string":
isNaN(parseFloat(a)) || void 0 != intX ? imperials.hasOwnProperty(a) ? typImp = a : metrics.hasOwnProperty(a) ? typMet = a : conversionTypes.hasOwnProperty(a) && (conType = conversionTypes[a]) : intX = parseFloat(a);
break;
case "object":
if (a instanceof Array) setVarz.apply(this, [a]);
else if (a instanceof Object)
for (h in a) {
var b = a[h];
conversionTypes.hasOwnProperty(h) ? conType = conversionTypes[h] : imperials.hasOwnProperty(h) ? (typImp =
h, void 0 != intX || isNaN(parseFloat(b)) || (intX = parseFloat(b))) : metrics.hasOwnProperty(h) ? (typMet = h, void 0 != intX || isNaN(parseFloat(b)) || (intX = parseFloat(b))) : setVarz.apply(this, [
[b]
])
}
}
}
};
setVarz(args);
if (!isNaN(parseFloat(intX)) && imperials.hasOwnProperty(typImp) && metrics.hasOwnProperty(typMet) && conversionTypes.hasOwnProperty(conType)) {
if (conType == 'metric') {
var inches = intX * imperials[typImp],
centimeters = inches * 2.54;
$ret = centimeters * metrics[typMet];
}
else if (conType == 'imperial') {
var centimeters = intX / metrics[typMet],
inches = centimeters / 2.54;
$ret = inches / imperials[typImp];
}
}
return toFixed ? parseFloat($ret.toFixed(toFixedX)) : $ret;
}
convertImperialMetric.imperials = {
inches: 1,
feet: 12,
yards: 36,
miles: 63360,
nautical: 72913.4
};
convertImperialMetric.metrics = {
yocto: 10000000000000000000000,
zepto: 10000000000000000000,
atto: 10000000000000000,
femto: 10000000000000,
pico: 10000000000,
nano: 10000000,
micro: 10000,
milli: 10,
centi: 1,
deci: .1,
meter: .01,
deka: .001,
hecto: .0001,
kilo: .00001,
mega: .00000001,
giga: .00000000001,
tera: .00000000000001,
peta: .00000000000000001,
exa: .00000000000000000001,
zetta: .00000000000000000000001,
yotta: .00000000000000000000000001
};
}
convertImperialMetric(12, 'inches', 'centi'); // Results in: 30.48
convertImperialMetric(30.48, 'centi', 'inches', 'i'); // Results in: 12
convertImperialMetric('1200000', 'inches', 'kilo'); // Results in: 30.480000000000004
convertImperialMetric('1200000', 'inches', 'kilo', true); // Results in: 30.48
convertImperialMetric('1200000', 'inches', 'kilo', true, 1); // Results in: 30.5
convertImperialMetric([ 12, 'inches', 'centi' ]); // Results in: 30.48
convertImperialMetric([ '12', 'inches', 'centi' ]); // Results in: 30.48
convertImperialMetric({ inches: 12, anyVariableName: 'centi' }); // Results in: 30.48
convertImperialMetric({ inches: '12', anyVariableName: 'centi' }); // Results in: 30.48
convertImperialMetric({ inches: 12, centi: 'anyValue' }); // Results in: 30.48
convertImperialMetric({ inches: '12', centi: 'anyValue' }); // Results in: 30.48
convertImperialMetric({ inches: '12', to: 'centi', type: 'metric', toFixed: true, toFX: 1 }); // Results in: 30.5
convertImperialMetric({ feet: 1 }, 'centi'); // Results in: 30.48
convertImperialMetric({ centi: '30.48' }, 'inches', 'imperial'); // Results in: 12
convertImperialMetric({ meter: '.3048' }, 'inches', 'imperial'); // Results in: 12
jsFiddle / jsFiddle/show