I have a table structured like this:
<table>
<tbody>
for loop here
<tr>
<td>Item X Attribute 1</td>
<td>Item X Attribute 2</td>
<td><button name="test" onclick="display_variants()">Hide my kids</button></td>
</tr>
<tr>
<tbody class="variants_info">
<tr>
<td>Item X Variant 1</td>
<td>Item X Variant 2</td>
</tr>
</tbody>
</tr>
endfor loop
</tbody>
</table>
So that structure repeats Y amount of times.
I'm trying to make a script that hides the tbody.variants
of the row selected.
What I have so far is this:
<script>
function display_variant(){
if($('.variants_info').is(":visible")){
$('.variants_info').hide();
}
else{
$('.variants_info').show();
}
}
</script>
but this hides the variants from ALL the rows.
Is there a way to select the childs of the specific row? Also how can I start with the tbody.variants
hidden? (Start as in when I visit the page).
Edit: At the moment is looking closely to this:
Update: I've managed to change the structure to this:
<table>
for loop
<tbody>
<tr>
<td>image for el 1</td>
<td>attr for el 1</td>
<td><button type='button' name='test'>Click Me</button></td>
</tr>
for loop
<tr class='variants_info'>
<td>variant1 for el 1</td>
<td>variant2 for el 1</td>
</tr>
endfor
</tbody>
endfor
</table>
Update 2: The actual code is this one:
<table class="pure-table pure-table-bordered">
<tbody>
{% for product in collection.products %}
{% if product.available %}
<tr class="{% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}" alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
{% for variant in product.variants %}
<tr>
<td>{{variant.title}}</td>
<td>{{variant.price | money }}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
<script>
$("td button").click(function(){
$(this).closest('tr').next().toggle();
})
</script>
I still can't get the JS to work.. =/ Current one is only hiding the first variant( Instead of all the variants for the clicked button )
Answer: Use the jQuery find() Method You can use the find() method to get the children of the $(this) selector using jQuery. The jQuery code in the following example will simply select the child <img> element and apply some CSS style on it on click of the parent <div> element.
The children() method returns all direct children of the selected element. The DOM tree: This method only traverse a single level down the DOM tree. To traverse down multiple levels (to return grandchildren or other descendants), use the find() method.
The ("parent > child") selector selects all elements that are a direct child of the specified element.
I can use $('#root > * > *') to get all its grandchildren.
I would suggest to mark the rows that contain the products with a class name, e.g. "product", like this:
<tr class="product {% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}"
alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
You would not add that class to the rows that have the variants.
Then in your JavaScript use the nextUntil
method to match all next variant rows (which do not have the "product" class) until, but excluding, the next product row, and apply the toggle()
method to all these:
$("td button").click(function(){
$(this).closest('tr').nextUntil('.product').toggle();
});
Instead of a single table, you could create nested tables, one for each product, containing the variants. It would look somewhat like this:
<table class="pure-table pure-table-bordered">
<tbody>
{% for product in collection.products %}
{% if product.available %}
<tr class="{% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}"
alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
<tr>
<table class="some other class specific for variants">
<tbody>
{% for variant in product.variants %}
<tr>
<td>{{variant.title}}</td>
<td>{{variant.price | money }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
This has advantages and disadvantages. The main disadvantage is that the columns of these sub-tables are not aligned with the columns in the main table. But it depends on what you want...
The JavaScript code would then have to be like you had it originally:
$("td button").click(function(){
$(this).closest('tr').next().toggle();
});
You could also wrap each "section" (consisting of one product row and the variant rows that belong to it) with a tbody
tag. Although not commonly done, this is allowed as stated on MDN:
Note that unlike the
<thead>
,<tfoot>
, and<caption>
elements however, multiple<tbody>
elements are permitted (if consecutive), allowing the data-rows in long tables to be divided into different sections, each separately formatted as needed.
This is different from your original HTML, where you had tbody
elements as children of tr
elements, which is invalid HTML.
It would look like this:
<table class="pure-table pure-table-bordered">
{% for product in collection.products %}
{% if product.available %}
<tbody>
<tr class="{% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}"
alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
{% for variant in product.variants %}
<tr>
<td>{{variant.title}}</td>
<td>{{variant.price | money }}</td>
</tr>
{% endfor %}
</tbody>
{% endif %}
{% endfor %}
</table>
You can then use the nextAll()
method to hide the variant rows, because they are delimited by the tbody
wrapper from the next product row:
$("td button").click(function(){
$(this).closest('tr').nextAll().toggle();
});
If you want the variants all to be hidden at first, then add the following attribute to those rows in the HTML code:
<tr style="display:hidden">
You would of course not do this for the product rows. Also, you might want to define a CSS class for this (e.g. tr.hidden { display:hidden; }
instead of using style
.
The jQuery toggle()
method will override this style
when showing, and restore it again when hiding.
Your HTML
is not valid so you can change that and then use this DEMO
$("td button").click(function() {
$(this).closest('tr').next().toggle();
})
try this one :-
$("td button").click(function() {
$(this).closest('tr').nextUntil("tbody").toggle();
});
the jsfiddle demo link is :- https://jsfiddle.net/Lg0wyt9u/776/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With