JacksWastedLife
JacksWastedLife

Reputation: 294

Best way to reuse JavaScript for common html elements

I have an HTML form that takes in values from a dropdown list. When an option is selected the HTML badge is updated to display the status of Good or Bad.

Each badge element span class is the same, but the ID is different as I need to capture the result.

Is there a way that I can use a single JavaScript function against all span classes but only update the span class for where the dropdown box is?

Or do I need to define every element ID within the JavaScript function.

The <span class="badge badge-soft-success" is on every badge.

const changeBadgeColour = document.getElementById('project-tier-entry-level');

changeBadgeColour.addEventListener('change', function() {
  var p_status = document.getElementById("project-tier-entry-level");
  p_status_value = p_status.options[p_status.selectedIndex].value;


  const statusBadge = document.getElementById('project-tier-entry-level-status');
  if (p_status_value === "Yes") {

    document.getElementById('project-tier-entry-level-status').className = 'badge badge-soft-success'
    document.getElementById('project-tier-entry-level-status').textContent = 'Good!'

  } else {
    document.getElementById('project-tier-entry-level-status').className = 'badge badge-soft-danger'
    document.getElementById('project-tier-entry-level-status').textContent = 'Bad!'
  }

  console.log()

});
<div class="col-sm-6">
  <label class="form-label" for="project-tier-entry-level-label">Does the project land in our Tiered entry levels?</label>
  <span class="badge badge-soft-success" id="project-tier-entry-level-status"></span>
  <select class="form-control" name="choices-single-no-sorting" id="project-tier-entry-level">
    <option value="" disabled selected hidden>Please Choose...</option>
    <option>Yes</option>
    <option>No</option>
  </select>
</div>

Upvotes: 1

Views: 127

Answers (2)

mplungjan
mplungjan

Reputation: 177940

You can delegate

document.getElementById('container').addEventListener('change', function(e) {
  const tgt = e.target;
  if (tgt.tagName === "SELECT" && tgt.id.startsWith("project-tier")) { // in case there are other things that can change in that container
    const yes = tgt.value === "Yes"
    const statusBadge = tgt.previousElementSibling; // or tgt.closest('div').querySelector('span.badge');
    statusBadge.classList.toggle("badge-soft-success", yes)
    statusBadge.classList.toggle("badge-soft-danger", !yes)
    statusBadge.textContent = yes ? 'Good!' : 'Bad!';
  }
});
<div id="container">
  <div class="col-sm-6">
    <label class="form-label" for="project-tier-entry-level-label">Does the project land in our Tiered entry levels?</label>
    <span class="badge badge-soft-success" id="project-tier-entry-level-status"></span>
    <select class="form-control" name="choices-single-no-sorting" id="project-tier-entry-level">
      <option value="" disabled selected hidden>Please Choose...</option>
      <option>Yes</option>
      <option>No</option>
    </select>
  </div>

  <div class="col-sm-6">
    <label class="form-label" for="project-tier-entry-level-label">Does the project land in our Tiered normal levels?</label>
    <span class="badge badge-soft-success" id="project-tier-normal-level-status"></span>
    <select class="form-control" name="choices-single-no-sorting" id="project-tier-normal-level">
      <option value="" disabled selected hidden>Please Choose...</option>
      <option>Yes</option>
      <option>No</option>
    </select>
  </div>
</div>

Three options with a result of the selections:

document.getElementById('container').addEventListener('change', function(e) {
  const tgt = e.target;
  if (tgt.tagName === "SELECT" && tgt.id.startsWith("project-tier")) { // in case there are other things that can change in that container
    const badge = tgt.value
    const statusBadge = tgt.previousElementSibling; // or tgt.closest('div').querySelector('span.badge');
    statusBadge.classList.toggle("badge-soft-success", badge==="Yes")
    statusBadge.classList.toggle("badge-soft-danger",  badge==="No")
    statusBadge.classList.toggle("badge-soft-unknown",  badge==="Unknown")
    const text = {"Yes":"Good!","No":"Bad!","Unknown":"Unknown!"}[badge] || "What?"
    statusBadge.textContent = text;
    
    const res =  [...document.querySelectorAll("#container select[id^=project-tier]")]
      .reduce((acc, sel) => {
        if (acc[sel.value] != undefined) acc[sel.value]++;
        else acc["Not set"]++;
        return acc
      },{"Yes":0,"No":0,"Unknown":0,"Not set":0})
    document.getElementById("result").value = Object.entries(res).map(([key,val]) => `${key}: ${val}`).join('\n')
  }
});
<form id="tierForm">
<div id="container">
  <div class="col-sm-6">
    <label class="form-label" for="project-tier-entry-level-label">Does the project land in our Tiered entry levels?</label>
    <span class="badge badge-soft-success" id="project-tier-entry-level-status"></span>
    <select class="form-control" name="choices-single-no-sorting" id="project-tier-entry-level">
      <option value="" disabled selected hidden>Please Choose...</option>
      <option>Yes</option>
      <option>No</option>
      <option>Unknown</option>
    </select>
  </div>

  <div class="col-sm-6">
    <label class="form-label" for="project-tier-entry-level-label">Does the project land in our Tiered normal levels?</label>
    <span class="badge badge-soft-success" id="project-tier-normal-level-status"></span>
    <select class="form-control" name="choices-single-no-sorting" id="project-tier-normal-level">
      <option value="" disabled selected hidden>Please Choose...</option>
      <option>Yes</option>
      <option>No</option>
      <option>Unknown</option>
      <option></option>
    </select>
  </div>
</div>
<div>
<textarea readonly id="result"></textarea>
</div>
</form>

Upvotes: 2

seriously
seriously

Reputation: 1367

How about if you assign the class name directly to your changeBadgeColour variable with querySelectorAll.

const changeBadgeColour = document.querySelectorAll('.badge .badge-soft-success')

Upvotes: 1

Related Questions