Why isn't this toggleClass() working?

74 Views Asked by At

I have a fairly straight-forward class toggle in jQuery. However I can't for the life of me figure out why it's not functioning as expected.

When clicking anywhere on the label, the class of the <p> should toggle. It works as expected if you click the checkbox. However, no toggle takes place if you click anywhere else

$('.xtrag p').on('click', function() {
  $(this).toggleClass('row9');
});
.xtrag {
  margin: 40px;
}
p {
  margin: 10px 0;
}
.row0 {
  background: #eee;
  padding: 4px 8px;
}
.row9 {
  background: #ffd;
}
.rt {
  float: right;
}
label {
  display: inline-block;
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="xtrag">
  <p class="row0">
    <label for="xg1">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="1" id="xg1" />
          </span>
      Item 1
    </label>
  </p>
  <p class="row0">
    <label for="xg2">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="2" id="xg2" />
          </span>
      Item 2
    </label>
  </p>
  <p class="row0">
    <label for="xg3">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="3" id="xg3" />
          </span>
      Item 1
    </label>
  </p>
</div>

What am I missing?

How can I toggle the class of the <p> when the label is clicked?

I've tried targeting the <label> and then using .parent() which doesn't change any of the behavior.

2

There are 2 best solutions below

1
mplungjan On BEST ANSWER

Test the change of the checkbox instead. The label triggered another click

$('.xtrag input').on('change',  function() {
  $(this).closest("p").toggleClass('row9');
});
.xtrag {
  margin: 40px;
}
p {
  margin: 10px 0;
}
.row0 {
  background: #eee;
  padding: 4px 8px;
}
.row9 {
  background: #ffd;
}
.rt {
  float: right;
}
label {
  display: inline-block; 
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="xtrag">
  <p class="row0">
    <label for="xg1">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="1" id="xg1" />
          </span>
      Item 1
    </label>
  </p>
  <p class="row0">
    <label for="xg2">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="2" id="xg2" />
          </span>
      Item 2
    </label>
  </p>
  <p class="row0">
    <label for="xg3">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="3" id="xg3" />
          </span>
      Item 1
    </label>
  </p>
</div>

2
Justinas On

It's because your input bubbles up click event and you get two event calls instead of one.

One way it would be to stop bubbling from input, other - check event target:

$('.xtrag p').on('click', function(e) {
  if (typeof $(e.target).attr('type') !== 'undefined') {
    $(this).toggleClass('row9');
  }
});
.xtrag {
  margin: 40px;
}
p {
  margin: 10px 0;
}
.row0 {
  background: #eee;
  padding: 4px 8px;
}
.row9 {
  background: #ffd;
}
.rt {
  float: right;
}
label {
  display: inline-block;
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="xtrag">
  <p class="row0">
    <label for="xg1">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="1" id="xg1" />
          </span>
      Item 1
    </label>
  </p>
  <p class="row0">
    <label for="xg2">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="2" id="xg2" />
          </span>
      Item 2
    </label>
  </p>
  <p class="row0">
    <label for="xg3">
      <span class="rt">
            <input type="checkbox" name="extrag[]" value="3" id="xg3" />
          </span>
      Item 1
    </label>
  </p>
</div>