Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== Resistor Calculator ====== I created this because during a term, I had to work with electronics and I always felt resistors were troublesome. I always lost track of what resistors I had and I felt it was troublesome calculating the amount of resistance each resistor had. Originally I created a local version which used websocket to save and read a record of the resistors I had. To make it work fully here on the web, I changed the code to not use websockets and allow for uploading and downloading resistor data. I also marked out and added buttons to some features which only had keybinds before. Originally the interface was inspired by the VIM editor but recently when I was porting my code to work fully on the web, I added mouse support. For touch devices touch the part of the interface to interact with it. To remove a color, press backspace or press the color boxes. <html> <style> html { background-color: silver; color: black; } #keypad { display: grid; grid-template-columns: auto auto auto auto auto auto; gap: 10px; background-color: #2196f3; padding: 10px; } #keypad > div { text-align: center; padding: 20px; font-size: 20px; transition: opacity 0.2s, color 0.2s; vertical-align: center; } /* CSS animations: https://www.w3schools.com/css/css3_transitions.asp */ /* https://stackoverflow.com/a/6900392/19515980 */ #keypad > div:hover { opacity: 0.8; cursor: pointer; } #container { display: flex; justify-content: space-between; /* Adjust spacing between items */ gap: 0.1px; /* Add space between the divs */ width: 30%; position: relative; left: 35%; color: black } .chosenKeys:hover { opacity: 0.5; cursor: pointer; } .chosenKeys { width: 50px; height: 50px; display: flex; align-items: center; /* Center content vertically */ justify-content: center; /* Center content horizontally */ background-color: magenta; border: 4px ridge pink; } .square { text-align: center; position: absolute; height: 5%; width: 10%; background-color: navy; color: white; padding: 1%; font-size: 25px; top: 1% } #first { left: 43%; } #second { left: 48%; } #third { left: 53%; } #fourth { left: 58%; } #fifth { display: none; left: 60%; } #black { background-color: black; color: white; } #brown { background-color: rgba(76, 26, 12, 1); color: white; } #red { background-color: red; color: white; } #orange { background-color: orange; color: black; } #yellow { background-color: yellow; color: black; } #green { background-color: green; color: black; } #blue { background-color: blue; color: white; } #violet { background-color: violet; color: black; } #grey { background-color: grey; color: white; } #white { background-color: white; color: black; } #gold { background-color: gold; color: black; } #silver { background-color: silver; color: black; } /*https://www.w3schools.com/html/html_tables.asp*/ h1 { text-align: center; } #results { text-align: center; font-size: 250%; font-weight: bold; } #mode { background-color: navy; color: white; } #upload{ background-color: white; color: black; } #download{ background-color: Indigo; color: white; } #find{ background-color: pink; color: black; } #save{ background-color: MintCream; color: black; } #calc{ background-color: LightSeaGreen ; color: black; } .highlight{ color: navy; } </style> <head> <title>Resistor Calculator</title> </head> <body style=" user-select: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; " > <!-- https://stackoverflow.com/a/3779567/19515980 --> <div id='container'> <div id="first" class="chosenKeys"></div> <div id="second" class="chosenKeys"></div> <div id="third" class="chosenKeys"></div> <div id="fourth" class="chosenKeys"></div> <div id="fifth" class="chosenKeys"></div> </div> <br /><br /> <div id="keypad"> <div id="black">Black<br />Q</div> <div id="brown">Brown<br />W</div> <div id="red">Red<br />E</div> <div id="orange">Orange<br />R</div> <div id="yellow">Yellow<br />T</div> <div id="green">Green<br />Y</div> <div id="blue">Blue<br />A</div> <div id="violet">Violet<br />S</div> <div id="grey">Grey<br />D</div> <div id="white">White<br />F</div> <div id="gold">Gold<br />G</div> <div id="silver">Silver<br />H</div> <div id="mode">Mode<br />Z</div> <div id="upload">Upload<br />X</div> <div id="download">Download<br />C</div> <div id="find">Find<br />?</div> <div id="save">Save<br />Ctrl + Rnter</div> <div id="calc">Calculate<br />Enter</div> </div> <br><br> <div id='results'></div> <input type="file" id="fileInput" style="display: none;" onchange="handleFileUpload(event)" accept=".json"> <script> // helped by chatgpt, w3schools, mdn function blobToString(e) { var reader = new FileReader(); reader.onload = function () { displayMessage(reader.result); // document.body.innerHTML+='<br>'+reader.result }; reader.readAsText(e.data); } //How to decode blob: https://stackoverflow.com/a/23024504 let combination = []; let allInputs = document.getElementsByClassName("chosenKeys"); allInputs = htmlCollectionToArray(allInputs); allInputs = allInputs.splice(0, allInputs.length - 1); let focusedElement = undefined; let keyShortCuts = [ { action: "black", key: "q", func: function () { addColors("black"); }, }, { action: "brown", key: "w", func: function () { addColors("brown"); }, }, { action: "red", key: "e", func: function () { addColors("red"); }, }, { action: "orange", key: "r", func: function () { addColors("orange"); }, }, { action: "yellow", key: "t", func: function () { addColors("yellow"); }, }, { action: "green", key: "y", func: function () { addColors("green"); }, }, { action: "blue", key: "a", func: function () { addColors("blue"); }, }, { action: "violet", key: "s", func: function () { addColors("violet"); }, }, { action: "grey", key: "d", func: function () { addColors("grey"); }, }, { action: "white", key: "f", func: function () { addColors("white"); }, }, { action: "gold", key: "g", func: function () { addColors("gold"); }, }, { action: "silver", key: "h", func: function () { addColors("silver"); }, }, { action: "removeColor", key: "Backspace", func: function (e) { removeColors("remove", e); }, }, { action: "calc", key: "Enter", func: function () { // sendColors(); getColorsAndCalc(); }, }, { action: "find", key: "?", func: function () { find(); }, }, { action: "mode", key: "z", func: function () { changeMode(); }, }, { action: "upload", key: "x", func: function () { upToDateSave = false; document.getElementById("fileInput").click(); }, }, { action: "download", key: "c", func: function () { handleFileDownload(); }, }, ]; function changeMode() { if (allInputs.length == 4) { allInputs = document.getElementsByClassName("chosenKeys"); allInputs = htmlCollectionToArray(allInputs); allInputs[4].style.display = "block"; } else if (allInputs.length == 5) { allInputs[4].style.display = "none"; allInputs = allInputs.splice(0, allInputs.length - 1); } } function find() { let finding = prompt( "Type the amount of resistance you are looking for in your resistor" ); results.innerHTML = findResistorMatch(JSON.parse(finding)); } function getColorsAndCalc() { for (let i = 0; i < allInputs.length; i++) { if ( allInputs[i].style.backgroundColor == "magenta" || allInputs[i].style.backgroundColor == "" ) { return "Please input" + allInputs.length + "colors."; } } let colors = []; for (let i = 0; i < allInputs.length; i++) { colors.push(allInputs[i].style.backgroundColor); allInputs[i].style.backgroundColor = "magenta"; } console.log("Combination entered: " + colors); results.innerText = JSON.stringify( calculateResistorAmount(reverseArray(colors)) ); } function addColors(toAdd) { for (let i = 0; i < allInputs.length; i++) { if ( allInputs[i].style.backgroundColor == "magenta" || allInputs[i].style.backgroundColor == "" ) { allInputs[i].style.backgroundColor = toAdd; return true; } if (i == allInputs.length - 1) { allInputs[i].style.backgroundColor = toAdd; } } } function removeColors(toAdd, e) { console.log(e) for (let i = 0; i < allInputs.length; i++) { if ( allInputs[allInputs.length - 1 - i].style.backgroundColor != "magenta" && allInputs[allInputs.length - 1 - i].style.backgroundColor != "" ) { allInputs[allInputs.length - 1 - i].style.backgroundColor = ""; return true; } } allInputs[allInputs.length - 1].style.backgroundColor = ""; } function runAction(action, e) { keyShortCuts.forEach((x) => { if (action == x.action) { console.log("running", x.action); x.func(e); if (e !== null) { animateClick(e) } } }); } function changingShortcuts(id, k) { keyShortCuts.forEach((x) => { if (x.action == id) { x.key = k; } }); } function checkColorSpelling(array) { let mistakes = []; array.forEach((x, i) => { let found = false; resistorColors.forEach((b) => { if (b.color == x) { found = true; } }); if (found != true) { mistakes.push(i); } }); return mistakes; } function addResistor(colorArray) { let found = false; if (checkColorSpelling(colorArray).length > 0) { return "Check spelling for " + checkColorSpelling(colorArray) + " ."; } existingResistors.forEach((x) => { if (checkArrayContents(x.colors, colorArray) == true) { found = true; x.amount += 1; } }); if (found == false) { existingResistors.push({ colors: colorArray, amount: 1 }); } } function checkArrayContents(array1, array2) { if (array1.length != array2.length) { return false; } let returnStatement = true; array1.forEach((x, i) => { if (x != array2[i]) { returnStatement = false; } }); return returnStatement; } function saveColors(e) { animateClick(document.getElementById('save')) upToDateSave = false; for (let i = 0; i < allInputs.length; i++) { if ( allInputs[i].style.backgroundColor == "magenta" || allInputs[i].style.backgroundColor == "" ) { return "Please input" + allInputs.length + "colors."; } } let colors = []; for (let i = 0; i < allInputs.length; i++) { colors.push(allInputs[i].style.backgroundColor); allInputs[i].style.backgroundColor = "magenta"; } console.log("Combination entered: " + colors); addResistor(colors); console.log("Color Saved"); results.innerText = "Resistor Record Added"; } document.addEventListener("keydown", function (e) { if (e.ctrlKey == true && e.key == "Enter") { saveColors(e); } else { keyShortCuts.forEach((x) => { if (x.key === e.key) { runAction(x.action, document.getElementById(x.action)); } }); } }); let keypadItems = keypad.children for (let i = 0; i < keypadItems.length; i++) { keypadItems[i].alt = getComputedStyle(keypadItems[i]).color } function animateClick (target) { console.log('target', target) target.style.color = 'transparent' setTimeout(() => { target.style.color = target.alt }, 100) } document .getElementById("container") .addEventListener("pointerdown", function (e) { removeColors("remove", e); }); document.getElementById("keypad").addEventListener("pointerdown", function (e) { console.log("cli", e.target.id); if (e.target.id === "save") { saveColors(e); } else { keyShortCuts.forEach((x) => { if (x.action == e.target.id) { runAction(x.action, document.getElementById(x.action)); } }); } }); function htmlCollectionToArray(collection) { let returnArray = []; for (let i = 0; i < collection.length; i++) { returnArray.push(collection[i]); } return returnArray; } function convertColorToNumber(input) { let output; if (typeof input == "string") { resistorColors.forEach((x) => { if (x.color == input) { output = x.n; } }); } else if (typeof input == "object") { output = input.map((b) => { let found; resistorColors.forEach((x) => { if (x.color == b) { found = x.n; } }); return found; }); } return output; } let resistorColors = [ { color: "black", n: 0, multiply: 1 }, { color: "brown", n: 1, multiply: 10, tolerance: 1 }, { color: "red", n: 2, multiply: 10 ** 2, tolerance: 2 }, { color: "orange", n: 3, multiply: 10 ** 3, tolerance: 3 }, { color: "yellow", n: 4, multiply: 10 ** 4, tolerance: 4 }, { color: "green", n: 5, multiply: 10 ** 5, tolerance: 0.5 }, { color: "blue", n: 6, multiply: 10 ** 6, tolerance: 0.25 }, { color: "violet", n: 7, multiply: 10 ** 7, tolerance: 0.1 }, { color: "grey", n: 8, multiply: 10 ** 8, tolerance: 0.05 }, { color: "white", n: 9, multiply: 10 ** 9 }, { color: "gold", n: NaN, multiply: 0.1, tolerance: 5 }, { color: "silver", n: NaN, multiply: 0.01, tolerance: 10 }, ]; function convertColorToMultiplier(input) { let output; if (typeof input == "string") { resistorColors.forEach((x) => { if (x.color == input) { output = x.multiply; } }); } else if (typeof input == "object") { output = input.map((b) => { let found; resistorColors.forEach((x) => { if (x.color == b) { found = x.multiply; } }); return found; }); } return output; } //Reverse and array. Make an array backwords.: function reverseArray(inputArray) { let returnArray = []; for (let i = 0; i < inputArray.length; i++) { returnArray.push(inputArray[inputArray.length - 1 - i]); } return returnArray; } function convertColorToTolerance(input) { let output; if (typeof input == "string") { resistorColors.forEach((x) => { if (x.color == input) { output = x.tolerance; } }); } else if (typeof input == "object") { output = input.map((b) => { let found; resistorColors.forEach((x) => { if (x.color == b) { found = x.tolerance; } }); return found; }); } return output; } function calculateResistorAmount(multiplier, tolerance, in1, in2, in3) { // console.log(multiplier); let resistor = {}; if (typeof multiplier == "object" && multiplier[0] == undefined) { return new Error( "Not a valid array. Object.colors and object.tolerance needs to be defined. An array needs the colors on the resistor. The first color should be the tolerance." ); } else if (typeof multiplier == "number" && in2 == undefined) { return new Error( "There should be at least for arguments and four colors on the resistor" ); } if (typeof multiplier == "object") { resistor.tolerance = multiplier[0]; resistor.multiplier = multiplier[1]; resistor.ins = multiplier.slice(2); } else if (typeof multiplier == "number") { resistor.tolerance = multiplier; resistor.multiplier = tolerance; resistor.ins = [in1, in2]; } if (in3 != undefined) { resistor.ins.push(in3); } let numbers = convertColorToNumber(resistor.ins); let nMultiplier = convertColorToMultiplier(resistor.multiplier); let nTolerance = convertColorToTolerance(resistor.tolerance); let total = 0; numbers.forEach((x) => { total += x; }); total *= nMultiplier; return { resistance: total, tolerance: nTolerance }; } let existingResistors = []; function findResistorMatch(amount) { if (existingResistors.length === 0) { alert( "No recorded resistors. Press x to upload a json file of the records of existing resistors" ); return false; } let resistorsToNum = existingResistors.map((x) => { return calculateResistorAmount(reverseArray(x.colors)).resistance; }); let found; resistorsToNum.forEach((x, i) => { if (x == amount) { found = i; } }); if (found != undefined) { return ( "Found resistor which has <strong class='highlight'>" + calculateResistorAmount( reverseArray(existingResistors[found].colors) ).resistance + " ohms </strong>of resistance and <strong class='highlight'>" + calculateResistorAmount( reverseArray(existingResistors[found].colors) ).tolerance + "% </strong>of tolerance. The color code is <strong class='highlight'>" + existingResistors[found].colors + " </strong>and there is/are <strong class='highlight'>" + existingResistors[found].amount + ". </strong>" ); } else { let closest; let foundIndex; existingResistors.forEach((x, i) => { if ( calculateResistorAmount(reverseArray(x.colors)).resistance == closestNumber(amount, resistorsToNum).number ) { closest = x; foundIndex = i; } }); return ( "No exact matching resistor has been found.\n The closest resistor that has required amount of resistance is the resistor has <strong class='highlight'>" + calculateResistorAmount(reverseArray(closest.colors)).resistance + " ohms </strong> of resistance and <strong class='highlight'>" + calculateResistorAmount(reverseArray(closest.colors)).tolerance + "% </strong> of tolerance. The color code is <strong class='highlight'>" + closest.colors + "</strong> and there is/are <strong class='highlight'>" + closest.amount + "</strong>." ); } } function closestNumber(inputNumber, checkArray) { let numberBefore = { number: undefined, difference: Infinity, }; let currentdifference; checkArray.forEach((x) => { currentdifference = inputNumber - x; if (currentdifference < 0) { // console.log('before',currentdifference) currentdifference -= currentdifference * 2; } // console.log('currentdifference',currentdifference) if (currentdifference < numberBefore.difference) { numberBefore.number = x; numberBefore.difference = currentdifference; } }); return numberBefore; } function handleFileUpload(e) { let file = e.target.files[0]; let reader = new FileReader(); reader.onload = function (e) { existingResistors.push(JSON.parse(e.target.result)); existingResistors = existingResistors.flat(); }; reader.readAsText(file); } let upToDateSave = false; // Function to handle file download function handleFileDownload() { upToDateSave = true; const data = existingResistors; const json = JSON.stringify(data, null, 2); const blob = new Blob([json], { type: "application/json" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "resistor-records.json"; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } document.addEventListener("visibilitychange", function (e) { if (upToDateSave === false) { e.preventDefault(); // alert('You may have entered data not saved to your local system. Save to not lose data. Data not saved to your system will be lost') e.returnValue = "You may have entered data not saved to your local system. Save to not lose data. Data not saved to your system will be lost"; return "You may have entered data not saved to your local system. Save to not lose data. Data not saved to your system will be lost"; } }); window.addEventListener("beforeunload", function (e) { if (upToDateSave === false) { e.preventDefault(); // alert('You may have entered data not saved to your local system. Save to not lose data. Data not saved to your system will be lost') e.returnValue = "You may have entered data not saved to your local system. Save to not lose data. Data not saved to your system will be lost"; return "You may have entered data not saved to your local system. Save to not lose data. Data not saved to your system will be lost"; } }); </script> </body> </html> resistor-calculator.txt Last modified: 2024/07/15 20:32by steve.wang