0

I have written a dice roller utility for a tabletop RPG in JavaScript.

Before I add more functionality to it, I would like to simplify the code by simplifying functions to remove unnecessary code.

When using the roller, some settings for rolls are changed by using menus. Each menu has its own function to pull the selected value into a global variable using document.getElementById.

There are 8 of these menus. But I need to add more menus to add more functionality. And I want to adapt this roller's code to make rollers for other games using the same system. (Names for IDs and variables would change.)

Instead of creating a new function for each menu, is it possible to pull a menu's ID into a variable that can be inserted into document.getElementById? For example, instead of:

MoonSettingSelected = document.getElementById("MoonPhaseMenu");

the code might read:

let SelectedSetting = document.getElementById("SelectedMenu");

I tried using QuerySelectorAll to pull data from the menus, but found it easier to use getElementById.

New to using JavaScript.

Sample code below is available on CodePen.

    <div class="centre RageOptions">
  <select id="MoonPhaseMenu" onclick="SetMoonPhase()" class="menu shadow">
    <option value="9999" selected>Moon phase</option>
    <option value="1">Full</option>
    <option value="2">Crescent</option>
    <option value="3">Half</option>
    <option value="4">Gibbous</option>
    <option value="5">New</option>
  </select>
</div>
<p>&nbsp</p>
<div>
  <div class="centre RageOptions">
    <select id="AuspiceMenu" onclick="SetAuspice()" class="menu shadow">
      <option value="9999" selected>Auspice</option>
      <option value="1">Ahroun</option>
      <option value="2">Theurge</option>
      <option value="3">Philodox</option>
      <option value="4">Galliard</option>
      <option value="5">Ragabash</option>
    </select>
  </div>
  <p>&nbsp</p>
  <div class="centre RageOptions">
    <select id="RankMenu" onclick="SetRank()" class="menu shadow">
      <option value="9999" selected>Rank</option>
      <option value="0">Cub (0)</option>
      <option value="1">Cliath (1)</option>
      <option value="2">Fostern (2)</option>
      <option value="3">Adren (3)</option>
      <option value="4">Athro (4)</option>
      <option value="5">Elder (5)</option>
      <option value="6">Legend (6)</option>
    </select>
  </div>
</div>
// CHANGE GLOBAL VARIABLES ON MENU SELECT

var MoonSetting = "9999";
var AuspiceSetting = "9999";
var GarouRank = Number(0);

function SetMoonPhase() {
  let MoonSettingSelected = document.getElementById("MoonPhaseMenu");
  MoonSettingSelected.addEventListener("change", function handleChange(event) {
    MoonSetting = Number(event.target.value);
  });
}

function SetAuspice() {
  AuspiceSettingSelected = document.getElementById("AuspiceMenu");
  AuspiceSettingSelected.addEventListener(
    "change",
    function handleChange(event) {
      AuspiceSetting = Number(event.target.value);
    }
  );
}

function SetRank() {
  // Set GarouRank global variable on menu change
  GarouRankSelected = document.getElementById("GarouRankMenu");
  GarouRankSelected.addEventListener("change", function handleChange(event) {
    GarouRank = Number(event.target.value);
  });
}

// …and repeat for 5 (and counting) functions, each of which is identical except for the ID in getElementById("…")
2
  • Yes, you can write const id ="something; and then const something = document.getElementById(id); if that's what you're asking. Commented Apr 3, 2023 at 16:01
  • When you click on say RankMenu the handler function’s this will refer to the element you clicked on. So you don’t need to get that element by id because it’s already contained in this. Commented Apr 3, 2023 at 16:47

2 Answers 2

1

You can use helper function to attach eventListeners. (ids and variable names changed for convenience)

const setMenuValue = (menuId) => {
  document.getElementById(menuId).addEventListener("change", ({target: {value}}) => {
    window[menuId] = Number(value);
    console.log(menuId, window[menuId])
  });
};

let MoonPhase = "9999";
let Auspice = "9999";
let Rank = 0;

setMenuValue("MoonPhase");
setMenuValue("Auspice");
setMenuValue("Rank");
.as-console-wrapper { max-height: 100% !important;  }
    <div class="centre RageOptions">
      <select id="MoonPhase" class="menu shadow">
        <option value="9999" selected>Moon phase</option>
        <option value="1">Full</option>
        <option value="2">Crescent</option>
        <option value="3">Half</option>
        <option value="4">Gibbous</option>
        <option value="5">New</option>
      </select>
    </div>
    <p>&nbsp</p>
    <div>
      <div class="centre RageOptions">
        <select id="Auspice" class="menu shadow">
          <option value="9999" selected>Auspice</option>
          <option value="1">Ahroun</option>
          <option value="2">Theurge</option>
          <option value="3">Philodox</option>
          <option value="4">Galliard</option>
          <option value="5">Ragabash</option>
        </select>
      </div>
      <p>&nbsp</p>
      <div class="centre RageOptions">
        <select id="Rank" class="menu shadow">
          <option value="9999" selected>Rank</option>
          <option value="0">Cub (0)</option>
          <option value="1">Cliath (1)</option>
          <option value="2">Fostern (2)</option>
          <option value="3">Adren (3)</option>
          <option value="4">Athro (4)</option>
          <option value="5">Elder (5)</option>
          <option value="6">Legend (6)</option>
        </select>
      </div>
    </div>

Sign up to request clarification or add additional context in comments.

2 Comments

This looks good for my needs. Is there a easy way to concat a string to menuId, so the variable has a different name from the menu it comes from?
For example: For variable named :MoonPhaseValue, you can add suffix using string literal : const variableName = `${menuId}Value`; window[variableName] = Number(value);
0

You could also try a for loop to create a list of all of the ids. Then you can pass in a variable like menu[j] or menu[0]. You can use variables when passed into document.getElementById, and I'm pretty sure you can create ID names with variables like "menu + i".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.