1

I'm struggling to find the error within my code. My function is triggered whenever an option is changed. I first cycle through all the selects to see which values have been selected. I then cycle through them again and then their children to HIDE all the options that have been taken. I am sure that there are other posts on stack overflow that have better ways of doing this, but I would rather have my original code. I can't find my error, though. I have put alerts everywhere but they are always called only once, even though the .length is > 1.

Thanks!

EDIT:

  • I just realized the problem was with the .removeAttr so if anyone could tell me how to fix that, that might be just the help I need.

$(document).on("change", function(e) {
  var hmmm = [];
  var facts = true;
  var allSelects = $(".student-three select");
  for (var i = 0; i < allSelects.length; i++) {
    if (allSelects[i].value != 0) {
      hmmm.push(allSelects[i].value);
    }
  }
  for (var i = 0; i < allSelects.length; i++) {
    for (var j = 0; j < allSelects[i].children.length; j++) {
      for (var z = 0; z < hmmm.length; z++) {
        if (allSelects[i].children[j].value == hmmm[z]) {
          allSelects[i].children[j].addAttr('hidden');
          facts = false;
        }
      }
      if (facts) {
        allSelects[i].children[j].removeAttr('hidden');
      }
    }
  }
});
<!DOCTYPE>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>

<body>
  <div class="student-three">
    Choice 1:
    <select name="C1">
      <option value='0'>Select One</option>
      <option value='1'>Option 1
      </option>
      <option value='2'>Option 2
      </option>
    </select><br>Choice 2:
    <select name="C2">
      <option value='0'>Select One</option>
      <option value='1'>Option 1
      </option>
      <option value='2'>Option 2 
      </option>
    </select><br>Choice 3:
    <select name="C3">
      <option value='0'>Select One</option>
      <option value='1'>Option 1 
      </option>
      <option value='2'>Option 2
      </option>
    </select>
  </div>

</body>

</html>
Bobby
  • 13
  • 3

2 Answers2

1

The problem is that jquery's operator [] not returns a jquery element; it returns a DOM element.

This element has no method removeAttr() (the equivalent is removeAttribute()), so you shoudl pass it to $() to get a jquery element.

Also, jquery hasn't addAttr() as opposite to removeAttr(). Instead, you should use attr(<>, true). See Add disabled attribute to input element using Javascript.

$(document).on("change", function(e) {
  var hmmm = [];
  var facts = true;
  var allSelects = $(".student-three select");
  for (var i = 0; i < allSelects.length; i++) {
    if (allSelects[i].value != 0) {
      hmmm.push(allSelects[i].value);
    }
  }
  for (var i = 0; i < allSelects.length; i++) {
    for (var j = 0; j < allSelects[i].children.length; j++) {
      for (var z = 0; z < hmmm.length; z++) {
        if (allSelects[i].children[j].value == hmmm[z]) {
          $(allSelects[i].children[j]).attr('hidden', true);
          facts = false;
        }
      }
      if (facts) {
        $(allSelects[i].children[j]).removeAttr('hidden');
      }
    }
  }
});
<!DOCTYPE>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>

<body>
  <div class="student-three">
    Choice 1:
    <select name="C1">
      <option value='0'>Select One</option>
      <option value='1'>Option 1
      </option>
      <option value='2'>Option 2
      </option>
    </select><br>Choice 2:
    <select name="C2">
      <option value='0'>Select One</option>
      <option value='1'>Option 1
      </option>
      <option value='2'>Option 2 
      </option>
    </select><br>Choice 3:
    <select name="C3">
      <option value='0'>Select One</option>
      <option value='1'>Option 1 
      </option>
      <option value='2'>Option 2
      </option>
    </select>
  </div>

</body>

</html>
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • Very nice. I would add a `facts = true` right after the for statement with the j. Otherwise the hidden/false code doesn't really do anything. – Bobby Sep 01 '19 at 03:22
1
  • Cache your selector const $allSelects = $(".student-three select");
  • .map() to array all the selected values
  • Use :gt(0) to skip the first hint option
  • use .prop() for the "hidden" property - with a callback with the needed logic
  • Use Array.includes() to check if a value exists in the selected values array

const $allSelects = $(".student-three select");

$allSelects.on("change", function() {

  const sel = $allSelects.get().map(el => el.value); // selected values to array
  $allSelects.find('option:gt(0)').prop('hidden', function() {
    return !this.selected && sel.includes(this.value);
  });
  
});
<div class="student-three">
  Choice 1:
  <select name="C1">
    <option value='0'>Select One</option>
    <option value='1'>Option 1</option>
    <option value='2'>Option 2</option>
    <option value='3'>Option 3</option>
  </select><br>Choice 2:
  <select name="C2">
    <option value='0'>Select One</option>
    <option value='1'>Option 1</option>
    <option value='2'>Option 2</option>
    <option value='3'>Option 3</option>
  </select><br>Choice 3:
  <select name="C3">
    <option value='0'>Select One</option>
    <option value='1'>Option 1</option>
    <option value='2'>Option 2</option>
    <option value='3'>Option 3</option>
  </select>
</div>

<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313