Resistor tool

by MightyPork

HTML

<div id="mainwrap">
	<h1>Resistor Tool</h1>
  
  <div>Enter color code:</div>

  <div id="palette">
    <span class="color black"></span>
    <span class="color brown"></span>
    <span class="color red"></span>
    <span class="color orange"></span>
    <span class="color yellow"></span>
    <span class="color green"></span>
    <span class="color blue"></span>
    <span class="color violet"></span>
    <span class="color gray"></span>
    <span class="color white"></span>
    <span class="color gold"></span>
    <span class="color silver"></span>
  </div>

  <div id="inputs">
    <input type="text" id="code">
    <input type="button" id="undo" value="undo">
    <input type="button" id="clear" value="clear">
  </div>

  <div id="result">  
    <div class="resistor"></div>    
    <div id="result-value"></div>
  </div>
</div>

SCSS

@mixin clr($name, $k, $bg, $fg) {
  &.$name {
    background-color: $bg;
    border: 1px solid darken($bg,10);
   
    &:after {
      content: $k;
      color: $fg;
    }
  }
}

html {
  background: #f3f5f6;
}

*, *:before, *:after {
	box-sizing: border-box;
}

.color {
  $w: 1.9em;
  flex-shrink: 0;
  flex-grow: 0;
  width: $w;
  height: $w;
  padding: 2px;
  margin: 2px;
  &:first-child {margin-left: 0}
  &:last-child {margin-right: 0}
  display: flex;
  text-align: center;
  cursor: pointer;
  border-radius: 2px;
  align-items: center;
  justify-content: center;
  
  &:active {
    position: relative;
    top: 1px;
  }
  
  @include clr(black,"K",#222,white);
  @include clr(brown,"M",brown,white);
  @include clr(red,"R",red,white);
  @include clr(orange,"O",orange,black);
  @include clr(yellow,"Y",yellow,black);
  @include clr(green,"G",green,white);
  @include clr(blue,"B",blue,white);
  @include clr(violet,"V",purple,white);
  @include clr(gray,"E",gray,white);
  @include clr(white,"W",white,black);
  @include clr(gold,"A",gold,black);
  @include clr(silver,"S",silver,black);
  
  &.white {
    border-color: #999;
  }
}

#inputs input {
  font-size: 105%;
}

#code {
  width: 294px;
}

#palette, #result-code {
  display: flex;
  justify-content: left;
}

#palette, #result {
  margin: 5px 0;
}

#mainwrap {
  width: 412px;
  margin: 0 auto;
  font-family: sans-serif;
}

h1 {
  margin: 0; padding: 0;
  margin-top: 20px;
  margin-bottom: 10px;
  text-align: center;
}

#result-value {
  margin-top: 5px;
  font-size: 105%;
}

@mixin band($name, $bg) {
  &.$name {
    background: linear-gradient(to bottom,
      0% lighten($bg,5), 
      50% $bg,
      100% darken($bg,20));
    border-left: 1px solid darken($bg,10);
    border-right: 1px solid darken($bg,10);
  }
}

.resistor {
  $leadLen: 80px;
  
  border: 1px solid silver;
  background: linear-gradient(to bottom, 0% #d0b069, 100% #635026);
  height: 50px;
  width: 200px;
  border-radius: 10px;
  margin: 15px...

JavaScript

var color2letter = {
  black: "K",
  brown: "M",
  red: "R",
  orange: "O",
  yellow: "Y",
  green: "G",
  blue: "B",
  violet: "V",
  gray: "E",
  white: "W",
  gold: "A",
  silver: "S",
};

var letter2color = {
  K: 'black',
  M: 'brown',
  R: 'red',
  O: 'orange',
  Y: 'yellow',
  G: 'green',
  B: 'blue',
  V: 'violet',
  E: 'gray',
  W: 'white',
  A: 'gold',
  S: 'silver',
};

var letter2number = {
  K: 0,
  M: 1,
  R: 2,
  O: 3,
  Y: 4,
  G: 5,
  B: 6,
  V: 7,
  E: 8,
  W: 9,
};

var letter2mult = {
  K: 1,
  M: 10,
  R: 1e2,
  O: 1e3,
  Y: 1e4,
  G: 1e5,
  B: 1e6,
  V: 1e7,
  A: 0.1,
  S: 0.01,
};

var letter2tol = {
  M: 1,
  R: 2,
  G: 0.5,
  B: 0.25,
  V: 0.1,
  E: 0.05,
  A: 5,
  S: 10,
};

var letter2ppm = {
  M: 100,
  R: 50,
  O: 15,
  Y: 25,
};

var all_letters = ["K", "M", "R", "O", "Y", "G", "B", "V", "E", "W", "A", "S"];

function isUndefined(val) {
	return typeof(val) == 'undefined';
}

function _fmtEng(value, base, name) {
	var kilos = Math.floor(value/base);
  var remain = value - kilos*base;
  var tenth = base/10;
  if (Math.abs(remain) < 0.000001) return kilos + name;
  var subrem = Math.floor(remain/tenth);
  console.log(subrem, remain, subrem*tenth);
  if (Math.abs(subrem*tenth - remain) < 0.000001) {
    return kilos + name + Math.round(remain/tenth);
  }
  return (value/base) + name;
}

function formatRValue(value) {
	if (value < 1e3) return _fmtEng(value, 1, 'R');
  if (value < 1e6) return _fmtEng(value, 1e3, 'k');
  return _fmtEng(value, 1e6, 'M');
}

function getPossibleResistorValues(code) {
	if (code.length < 3) return [];
  
  if (code.length == 3) {
  	return [
    	parseResistor(code, 4),
      parseResistor(code, 4, true)
    ];
  }
  
  if (code.length == 4) {
  	return [
    	parseResistor(code, 4),
      parseResistor(code, 5),
    	parseResistor(code, 4, true),
      parseResistor(code, 5, true),
    ];
  }
  
  if (code.length == 5) {
  	return [
    	parseResistor(code, 5),
    	parseResistor(code, 5, true),
    ];
  }
  
...