You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eval-code.mjs 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. const $ = document.querySelector.bind(document);
  2. const prepareInputs = (variables, onChange) => {
  3. const inputEl = $("#input");
  4. for (const node of [...inputEl.childNodes]) {
  5. node.remove();
  6. }
  7. for (const variable of variables) {
  8. const input = document.createElement("input");
  9. input.setAttribute("type", "text");
  10. input.setAttribute("placeholder", `${variable.slice(4)}`);
  11. input.setAttribute("value", "");
  12. input.addEventListener("keyup", () => {
  13. let value = Number(input.value);
  14. if (isNaN(value)) {
  15. value = 0;
  16. }
  17. onChange(variable, value);
  18. });
  19. inputEl.appendChild(input);
  20. }
  21. }
  22. const updateOutput = (result) => {
  23. // Float truncation
  24. if (typeof result === "number" && Math.floor(result) !== result) {
  25. result = result.toFixed(2);
  26. }
  27. const $ = document.querySelector.bind(document);
  28. const outputEl = $("#output");
  29. outputEl.innerText = result;
  30. }
  31. export default ({ code, variables }) => {
  32. const varList = [...variables].sort((a, b) => a.localeCompare(b));
  33. const fn = new Function(...varList, `return (${code});`);
  34. const values = new Map(varList.map((val) => [val, 0]));
  35. const refresh = () => {
  36. const result = fn(...varList.map((val) => values.get(val)));
  37. if (isNaN(result)) {
  38. throw new Error("Output was not a number")
  39. }
  40. $("#error").innerText = "";
  41. updateOutput(result);
  42. }
  43. const onChange = (variable, value) => {
  44. values.set(variable, value);
  45. refresh();
  46. }
  47. prepareInputs(varList, onChange);
  48. refresh();
  49. }