How to target child class and hide the parent one [duplicate] - javascript

How can I select the <tr> containing the child <div class="test">, as below?
<table>
<tr> <!-- this tr is what I want to select -->
<td>
<div class="test"> text </div>
</td>
</tr>
</table>

You can use parents or closest for that, depending on your needs:
$("div.test").parents("tr");
// Or
$("div.test").closest("tr");
(The initial selector can be anything that matches your div, so ".test" would be fine too.)
parents will look all the way up the tree, possibly matching multiple tr elements if you have a table within a table. closest will stop with the first tr it encounters for each of the divs.
Here's an example using closest:
Live copy | Live source
HTML:
<table>
<tr id="first"> <!-- this tr I want to select -->
<td>
<div class="test"> text </div>
</td>
</tr>
<tr id="second"> <!-- this tr I want to select -->
<td>
<div class="test"> text </div>
</td>
</tr>
<tr id="third"> <!-- this tr I want to select -->
<td>
<div class="test"> text </div>
</td>
</tr>
</table>
JavaScript:
jQuery(function($) {
var rows = $("div.test").closest("tr");
display("Matched " + rows.length + " rows:");
rows.each(function() {
display("Row '" + this.id + "'");
});
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
});
Output:
Matched 3 rows:
Row 'first'
Row 'second'
Row 'third'

Use selector :has() like:
$("tr:has(div.test)");
Find jQuery documentation here :has() Selector

$('.test').parent('tr')
this selects exactly what you want.

you should use
$('.test').parents('tr');
For Example:
http://jsfiddle.net/7T9nN/

The below targets the parent with class of .test somewhere within its children and in the below example changes background to red...
$(document).ready(function(){
$('.test').parents('tr').css('background-color', 'red');
});
For me this is extremely powerful when trying to target exported html from indesign. Powerful because indesign does not let you tag 's but through this you can tag a and then the through this JQuery.

$('.test').parent().parent(); or $('.text').parent().closest('tr');

Related

Using same Class to use the click method to show the nearest hidden element by its class

What I am trying to achieve: What I am trying to achieve is very simple I have a table with 2 table body tags. The first one gets shown as its just the main content. The last td element has an anchor tag, this anchor tag when clicked should show the next tbody tag using the jQuery method slideToggle().
Problem: The problem I am having is these are dynamically made tables using Angular.js. So if there are 5 items then there are 5 div elements each with a table that all have the same class for each tbody within the div. This makes sense as for each I would like the click function to show that specific tables second div if the user wants to see additional content related to that item.
Things tried:
$(this).next('.test').slideToggle();
$(this).closest('tbody').find('.test').slideToggle();
$(this).closest('.test').slideToggle();
$(this).closest('tr').find('.test').slideToggle();
Posts look into on StackOverflow for similar issue:
affect only the clicked element in jquery for multiple elements with same class
Using a class name in jQuery's .closest()
jQuery closest(); not working
Jquery adding click function to several spans with the same Class
Non Stack Overflow sites:
https://www.sitepoint.com/jquerys-closest-parents/
HTML:
<div class="productsList" ng-repeat="products in productListing.products">
<div class="productSection">
<div class="figureDiv">
<figure class="img">
<img ng-src="{{products.image}}" />
</figure>
</div>
<div class="description">
<h2 ng-bind="products.summary"></h2>
<summary ng-bind="products.description"></summary>
</div>
<table class="productTable">
<tbody>
<tr><td><b>Product Name</b></td><td ng-bind="product.merchantName"></td></tr>
<tr><td><b>Valid:</b></td><td>{{products.validityStart}} to {{products.valididtyEnd}}</td></tr>
<tr><td><b>Product Type:</b></td><td>Appliance</td></tr>
<tr><td><b>Testing:</b></td><td>Yes<a class="testLink" href="">Show More ></a></td></tr>
</tbody>
<tbody class="test">
<tr><td><b>Extra</b></td><td>Extra</td></tr>
<tr><td><b>Extra</b></td><td>Extra</td></tr>
<tr><td><b>Extra</b></td><td>Extra</td></tr>
<tr><td><b>Extra</b></td><td>Extra</td></tr>
</tbody>
</table>
</div>
</div>
jQuery (current implementation):
function init() {
jQuery(document).ready(function(){
$(document).on("click", ".productTable .testLink", function (ev) {
ev.stopImmediatePropagation();
$(this).closest('tr').find('.test').slideToggle();
$(".test").slideToggle();
});
}
Visually from Dynamic content (3 items):
Table class="productTable"
tbody
anchor tag class="testLink"
tbody class="test"
Table class="productTable"
tbody
anchor tag class="testLink"
tbody class="test"
Table class="productTable"
tbody
anchor tag class="testLink"
tbody class="test"
Ending
As you can see visually there are 3 tables created each having same classes. So for the first table if the user clicks the anchor tag then the body tag right after in that specific table will be displayed with toggle. Only that one should be shown not all of them which is the current problem.
I tried many solutions however nothing is working, every implementation is making all of them toggle which is horrible.
I think something like this.
$(".productTable .testLink").on("click", function() {
$(this).parents('.productTable').children('.test').slideToggle();
});
.testLink {
color: blue;
text-decoration: underline;
}
.test {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="productTable">
<tbody>
<tr>
<td><b>Product Name</b>
</td>
<td ng-bind="product.merchantName"></td>
</tr>
<tr>
<td><b>Valid:</b>
</td>
<td>{{products.validityStart}} to {{products.valididtyEnd}}</td>
</tr>
<tr>
<td><b>Product Type:</b>
</td>
<td>Appliance</td>
</tr>
<tr>
<td><b>Testing:</b>
</td>
<td>Yes<span class="testLink">Show More ></span>
</td>
</tr>
</tbody>
<tbody class="test">
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
</tbody>
</table>
I think the problem is in this line of your jQuery $(".test").slideToggle(); as it will execute slideToggle on all .test try removing it. Also update.closest('tr'); to .closest('table'); as the .test is in the table tag not the tr
From what I make out, you are looking for JQuery's .next() method. Just for the parent tbody and call .next()
Example would be
$('.testLink').parentsUntil('tbody').next().show();

Traversing on each span under table > tr > td > div

How to traverse on each span under table > tr > td > div ?
I would like to hide those span elements once click on the anchor tag that beneath the same tr level.
JSFiddle
$(document).ready(function() {
$(".hide").click(function(){
$('#table td div span').each(function(){
var $span = $(this);
$(this).siblings().hide();
var spanattr = $span.attr('class');
alert(spanattr);
});
});
});
HTML:
<table id="table">
<tbody>
<tr>
<td class="tdspan">
<div class="container">
<span class="spanelem">First</span>
</div>
</td>
<td class="tdspan">
<div class="container">
<span class="spanelem">Second</span>
</div>
</td>
<td class="tdspan">
<div class="container">
<span class="spanelem">3rd</span>
</div>
</td>
<td>
Hide
</td>
</tr>
</tbody>
<br>
</table>
<span id="text"></span>
I already searched for other questions and used the provided solution such as below link but I'm not able to figure it out.
jquery to traverse the div and get its span details
You don't need for loops there.
Simply .find() span with class .spanelem in a closest <tr> parent of the clicked element:
$(".hide").click(function(){
$(this).closest('tr').find('.spanelem').hide();
// Or using selector context (.find() equivalent but a bit shorter)
// $('.spanelem', $(this).closest('tr')).hide();
});
JSFiddle JSFiddle
References:
.closest()
.find()
selector context
Are you just trying to hide the spans themselves? You are hiding their siblings, and since they are the only children of their parent div, there is nothing else to hide. If you want to hide the spans themselves, then just change
$(this).siblings().hide();
to
$(this).hide();
If you have multiple rows, then you can just crawl up the tree from the .hide button that was clicked to its ancestor row, then find all the spans within that row. You may want to search on a particular class, or all spans, but I don't know for sure how you identify which elements you want to hide.
Something like
$(this).closest('tr').find('span').each(function() {
Updated JSFiddle here: https://jsfiddle.net/fk9jgrLx/4/
If your table structure is as in provided example, and if you will have multiple rows:
$(document).ready(function() {
$(".hide").click(function(){
$(this).parent().siblings().find('span').hide();
});
});
https://jsfiddle.net/L1j9psz6/1/ - remove all spans from row...

Finding child elements of a cloned element in jQuery

I don't know why I'm stuck on this but I am! Trying to clone a div and then modify its contents using children in jQuery. I am missing something here because it's not working as I would expect. See fiddle: http://jsfiddle.net/v7A2T/
Javascript (jQuery):
$test = $('#clone-container').clone().appendTo('#append');
$test.children('h2').text('my clone'); // works
$test.children('.remove-row').remove(); // doesn't work
And the HTML:
<div id="clone-container" class="hidden">
<h2>Location name</h2>
<div class="table-responsive">
<table class="table">
<thead>
<th>one</th><th>two</th><th>three</th>
<th>four</th><th>five</th><th>six</th>
</thead>
<tbody>
<tr class="remove-row"><td colspan="6">Remove this text from clone</td></tr>
</tbody>
</table>
</div> <!-- .table-responsive -->
</div>
<div id="append"></div>
.remove-row is not a direct child of the cloned element. Replace this:
$test.children('.remove-row').remove();
with this:
$test.find('.remove-row').remove();
Fiddle
Lets say i have cloned a TR and i want to search a button in the TD of the TR then i can do like this. The button has the class "green".
var tr = $(this).closest("tr").clone();
tr.children().find('button.green').hide(); // or show

Using each() for checking which class is clicked

So here's my problem, I'm new to jQuery. What I am trying to do here is check for user to click on a certain table cell/row and it would then display a div named popup of an index the same as the table cell votes. Without having to make separate functions of all the rows in my table.
Using some numerical value will display all the dialogs from a click of the cell of the same value the first time and from the second time only the correct one.
I bet there's some other way to do it and maybe there's just a stupid error.
Using the index value in the click and dialog function won't work.
I am open to suggestions on improvement also.
The scripts:
<script type='text/javascript'>
$(document).ready( function() {
$('.votes').each(function(index) {
$('.votes:eq(index)').click(function() {
$('.popup:eq(index)').dialog();
});
});
});
</script>
HTML for the table part, only a snippet
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
HTML for the div part, only a snippet of the div:
<div class='popup'>
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class='popup'>
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
jsFiddle Demo
You don't have to iterate using each for .click, that will happen internally. You can use .index() to get the index of the element clicked with reference to its parent.
$('.votes').click(function() {
$('.popup').eq($(this).index()).dialog();
});
Initially, the main problem is that you are not using string concatenation to apply the index to the selector (demo):
$('.votes:eq(index)')
// the Sizzle selector engine doesn't know what the string "index" is.
instead of
$('.votes:eq(' + index + ')')
// using concatenation calls the .toString() method of index to apply "0" (or "1", "2", etc.)
// so that the parsed string becomes '.votes:eq(0)' which the Sizzle selector engine understands
Once the Sizzle selector engine understands which elements to target (demo), the second problem is how jQueryUI changes the DOM with the .dialog method.
Inital markup:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
Once the first click event is handled, one of the div.popup elements is transformed into a jQueryUI Dialog and is appended to the body, removing it from its initial position, like so:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
<div class="ui-dialog ui-widget ..."> ... </div>
So your initial indexes no longer apply. Fortunately, there are several solutions to both problems (a few of which I've listed below).
Solutions to Problem 1:
Use string concatenation as described above.
Use the .eq method instead, which will accept the index variable as-is
Use a delegate handler instead and grab the index from within the handler:
Example of 2:
$('.votes').eq(index);
Example of 3:
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.parent().index(vote);
});
Solutions to Problem 2:
Create all of the dialogs initially and open them as needed.
Create the dialogs using a deep clone of the div element. (Not recommended)
Remove the td element to match the removed and re-appended div element. (Not recommended)
Example of 1:
var popups = [];
$('.popup').each(function (i, elem) {
var popup = $(elem).data('index', i).dialog({
"autoOpen": false
});
popups.push(popup)
});
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.index();
popups[index].dialog('open');
});
I'm sure there are other solutions as well, but these are the ones I thought of of the top of my head.
Functional demo: http://jsfiddle.net/2ChvX/2/
UPDATE:
With your chosen table structure, you're actually looking for the index of the parent tr element as that is what corresponds with the div.popup element. To get the index of the parent tr element, change the line that gets the index from:
index = vote.index();
to:
index = vote.parent().index();
Updated fiddle: http://jsfiddle.net/AZpUQ/1/
Updated
FWIW, here's an example using the jQueryUI dialog (which I presume you are using?) and javascript sectionRowIndex and cellIndex.
Reusable code allowing you to identify the cell the user clicked in and perform appropriate action.
http://jsfiddle.net/KbgcL/1/
HTML:
<table id="myTable">
<tr>
<th>Label:</th>
<th>Washington</th>
<th>Idaho</th>
<th>California</th>
</tr>
<tr>
<td class='label'>Votes</td>
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
</tr>
<tr>
<td class='label'>Voters</td>
<td class='voters'>5,000</td>
<td class='voters'>15,000</td>
<td class='voters'>25,000</td>
</tr>
</table>
<div id="msg"></div>
jQuery/javascript:
var myTr;
$('#msg').dialog({
autoOpen:false,
title: 'Report:'
});
$('#myTable tr td').click(function() {
myTr = $(this).closest('td').parent()[0].sectionRowIndex;
myCell = this.cellIndex;
myState = $('#myTable').find('tr:eq(0)').find('th:eq(' +myCell+ ')').html();
myVoters = $('#myTable').find('tr:eq(' +myTr+ ')').find('td:eq(' +myCell+ ')').html();
if (myTr==2 && myCell==3){
//California
$('#msg').html('There are ' +myVoters+ ' voters in ' +myState);
$('#msg').dialog('open');
}else if(myTr==1 && myCell==1){
$('#msg').html('There were ' +myVoters+ ' votes made in ' +myState);
$('#msg').dialog('open');
}
});

Jquery Get last row of table within last element in a series

I have a series of slides based off of sections:
<div id="slides">
<section id="first">
<section>
<table>
<thead>
</thead>
<tbody>
<tr id="somethingUnique">
...
</tr>
</tbody>
</table>
</section>
<section>
<table>
<thead>
</thead>
<tbody>
<tr id="somethingUnique">
...
</tr>
</tbody>
</table>
</section>
...
</section>
</div>
I need to select grab the ID of the last row from the table in the last section of #first section.
I'm using the following Jquery, getting "undefined" back...any ideas?
var lastListItem = $('#first:last-child table>tbody>tr:last').attr("id");
alert(lastListItem);
$('#first table:last tr:last')
or:
$('#first tr:last')
http://jsfiddle.net/hunter/QMzHH/
var lastListItem = $("#first").find("section").last().find("tr").last().attr("id");
I prefer using [0].id instead of .attr("id") since its one less method call; however, if you're not positive that you'll always have a table in that DOM position, attr is safer.
var lastListItem = $('#first section:last table tr:last').attr("id");
.find():
Get the descendants of each element in the current set of matched
elements, filtered by a selector, jQuery object, or element.
​$("#first")​.find("tr:last").attr("id")
or more simply in this case:
$("#first tr:last").attr("id")
EXAMPLE
The other answers work but the problem with your attempt is the fact that
:last-child has to be applied to the child element (section), not the parent (#first). The following should work
$('#first section:last-child table>tbody>tr:last').attr("id");
And could be simplified to
$('#first section:last-child tr:last-child').attr("id");
http://jsfiddle.net/e7mUD/1

Categories

Resources