1

I need to click an individual element within a set of elements, and select both that and an element from a different set but with the same index. each set usually consists of 2 to 6 indexes in the array (below example has 3: [ 0, 1, 2 ]), and both sets (the form radio buttons and the data itself) always have the matching number of indexes.

For example: When index 1 is clicked in the form, only the data bearing index 1 should be visible. All elements in the data set that are not clicked should hide since only 1 should show at a time. If index 1 is clicked, I should see [ 5g, 7g, 3g ] (the second index of each row). if index 0 is clicked, i should see [ 54mg, 76mg, 15mg ] (the 1st index of each row).

Clicking the data itself should not have any effect.

Here is what I tried:

<div>
  <form id="form" method="get" onsubmit="return false"></form>
  <label for="foo_0" set="foo" state="hidden">Option 1</label>
  <input form="form" name="fooItem" id="foo_0" index="0" type="radio" set="foo" style="display: none;" />
  <label for="foo_1" set="foo" state="visible">Option 2</label>
  <input form="form" name="fooItem" id="foo_1" index="1" type="radio" set="foo" style="display: none;" />
  <label for="foo_2" set="foo" state="hidden">Option 3</label>
  <input form="form" name="fooItem" id="foo_2" index="2" type="radio" set="foo" style="display: none;" />
</div>
<br />
<br />
<div class="row">
  <div class="rowName">Title 1</div>
  <div class="rowData">
    <div set="foo" index="0" state="hidden">54mg</div>
    <div set="foo" index="1" state="visible">5g</div>
    <div set="foo" index="2" state="hidden">123g</div>
  </div>
</div>
<div class="row">
  <div class="rowName">Title 2</div>
  <div class="rowData">
    <div set="foo" index="0" state="hidden">76mg</div>
    <div set="foo" index="1" state="visible">7g</div>
    <div set="foo" index="2" state="hidden">105g</div>
  </div>
</div>
<div class="row">
  <div class="rowName">Title 3</div>
  <div class="rowData">
    <div set="foo" index="0" state="hidden">15mg</div>
    <div set="foo" index="1" state="visible">3g</div>
    <div set="foo" index="2" state="hidden">87g</div>
  </div>
</div>
label[state=visible] {
  border: 1px solid #333333;
}
label[state=hidden] {
  border: 1px solid #cccccc;
}

.row {
  width: 100%;
  margin-top: 6px;
  margin-bottom: 4px;
  padding-bottom: 2px;
  border-bottom: 1px solid #cccccc;
  overflow: auto;
}

.row > .rowName {
  display: inline-block;
}

.row > .rowData {
  display: inline-block;
  float: right;
}

.row > .rowData > div[state=visible] {
  display: inline-block;
}
.row > .rowData > div[state=hidden] {
  display: none;
}

.row > .rowData > div[state=visible] {
  display: inline-block;
  width: 60px;
  
  text-align: right;
}
.row > .rowData > div[state=hidden] {
  display: none;
}

The $(this) works fine, but the 2 lines below it do not.

$(document).ready(function() {
  
  $('label[set="foo"]').on("click", function() {
    
    $(this).attr("state", "visible");
    $(this).siblings().attr("state", "hidden");
    
    $('.row > .rowData > div[set="foo"]').attr("state", "visible");
    $('.row > .rowData > div[set="foo"]').siblings().attr("state", "hidden");
    
  });
  
});

How do i select the ".row -> .rowData -> div" based on what index was clicked in "label"?

1 Answers1

0

Could you get the index value from the clicked element:

const index = $(this).attr("index");
$(`.row div[index=${index}]`).siblings().attr("state", "hidden");
$(`.row div[index=${index}]`).attr("state", "visible");

and then use that to select any div's inside a .row class element, with index as an attribute, with the value of the index clicked?

It might also be better to hide everything first, then display the new rows

EDIT:

$(this).attr('index') gets the actual index attr.

$(this).index() gets the index of the element compared to siblings in parent.

The below demonstrates both using $(this).index() and $(this).attr('index'), though, for the latter I needed to tweak the way your HTML was setup.

$(document).ready(function() {
  
  $('form[set="foo"] span').on("click", function() {
    
    $(this).attr("state", "visible");
    $(this).siblings().attr("state", "hidden");
    
    // $(this).attr('index') // Gets the actual index attr
    // $(this).index() // Gets the index of the element compared to siblings in parent
    
    $(`.row div[index="${$(this).attr('index')}"]`).attr("state", "visible");
    $(`.row div[index="${$(this).attr('index')}"]`).siblings().attr("state", "hidden");
    
  });
  
});
label[state=visible] {
  border: 1px solid #333333;
}
label[state=hidden] {
  border: 1px solid #cccccc;
}

.row {
  width: 100%;
  margin-top: 6px;
  margin-bottom: 4px;
  padding-bottom: 2px;
  border-bottom: 1px solid #cccccc;
  overflow: auto;
}

.row > .rowName {
  display: inline-block;
}

.row > .rowData {
  display: inline-block;
  float: right;
}

.row > .rowData > div[state=visible] {
  display: inline-block;
}
.row > .rowData > div[state=hidden] {
  display: none;
}

.row > .rowData > div[state=visible] {
  display: inline-block;
  width: 60px;
  
  text-align: right;
}
.row > .rowData > div[state=hidden] {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <form id="form" method="get" onsubmit="return false" set="foo">
    <span index="0">
      <label for="foo_0" state="hidden">Option 1</label>
      <input form="form" name="fooItem" id="foo_0" type="radio" set="foo" style="display: none;" />
    </span>
    <span index="1">
      <label for="foo_1" state="visible">Option 2</label>
      <input form="form" name="fooItem" id="foo_1" type="radio" set="foo" style="display: none;" />
    </span>
    <span index="2">
      <label for="foo_2" state="hidden">Option 3</label>
      <input form="form" name="fooItem" id="foo_2" type="radio" set="foo" style="display: none;" />
    </span>
  </form>
</div>
<br />
<br />
<div class="row">
  <div class="rowName">Title 1</div>
  <div class="rowData">
    <div set="foo" index="0" state="hidden">54mg</div>
    <div set="foo" index="1" state="visible">5g</div>
    <div set="foo" index="2" state="hidden">123g</div>
  </div>
</div>
<div class="row">
  <div class="rowName">Title 2</div>
  <div class="rowData">
    <div set="foo" index="0" state="hidden">76mg</div>
    <div set="foo" index="1" state="visible">7g</div>
    <div set="foo" index="2" state="hidden">105g</div>
  </div>
</div>
<div class="row">
  <div class="rowName">Title 3</div>
  <div class="rowData">
    <div set="foo" index="0" state="hidden">15mg</div>
    <div set="foo" index="1" state="visible">3g</div>
    <div set="foo" index="2" state="hidden">87g</div>
  </div>
</div>
Adam
  • 1,294
  • 11
  • 24
  • Unfortunately this did not work. I tried a few variations but none had any effect. I agree we should hide the values first though. – FigureOfCode Jun 25 '23 at 03:34
  • index is undefined in the example. i found the solution to getting the index here.. https://stackoverflow.com/questions/5545283/get-index-of-clicked-element-in-collection-with-jquery. const index = $('label[set="foo"]').index(this); bizarrely, using $(this) did not work. const index = $(this).index(this); if you can update your answer and test if it works, I will accept it. – FigureOfCode Jun 25 '23 at 04:21
  • No probs, I've updated my answer clarifying why that works and with a solution in a snippet. – Adam Jun 25 '23 at 14:20
  • The changes to the html break the labels. it's supposed to highlight the chosen selection by giving it a darker border so we know which one is selected. when changing the jquery to select the children, the siblings() doesn't suppress the border because they are no longer siblings. I think a pure css solution might work better for this anyway, since it needs to highlight regardless if the mouse is used or a keyboard. I need to make sure accessibility is maintained (which also necessitates i no longer hide the radio buttons). I wasn't aware that broke keyboard access until now.. – FigureOfCode Jun 25 '23 at 19:02
  • 1
    if the label goes after the radio input, we can use this css, then we can get rid of the first 2 lines of the jquery inside the jquery selection. this works for both keyboard and mouse. after this, it might be good: ... form[set=foo] > span > input + label { border: 1px solid #cccccc; } form[set=foo] > span > input:checked + label { border: 1px solid #333333; } – FigureOfCode Jun 25 '23 at 19:11