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

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

Related

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

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');

HTML and JS, hide tome table inside divs

I have a code like this:
I have some html code like this:
<div id="mapLegendInside">
<div>
<table>
// code
</table>
<div>
<table class="esriLegendLayerLabel">
// code
</table>
<table class="esriLegendLayer"> <--- I need to hide this table
// code
</table>
<table class="esriLegendLayer">
// code
</table>
</div>
</div>
</div>
I need to set style="display: none" the table that I've pointed, the first one with class="esriLegendLaye. Right now, I can do this:
document.getElementById("mapLegendInside").style["display"] = "none";
And I will hide the whole main div but, how can I pick only the table that I've pointed? Please, I can't add class or id to the tables or divs inside, this code is generated byt an external javascript library, I just need to pick that 2nd table inside the 2nd element (div) inside the div of the main div (haha).
here's a fiddle with that code to play with:
https://jsfiddle.net/pmiranda/coe0wa67/
You can use document.querySelector or querySelectorAll.
// you can use `document.querySelector`
document.querySelector('#mapLegendInside table.esriLegendLayer').style.display = 'none';
// or - use `querySelectorAll`
setTimeout(() =>
document.querySelectorAll('#mapLegendInside table.esriLegendLayer')[0].style.display = 'block', 1000);
<div id="mapLegendInside">
<div>
<table>
<tr>
<td>Code</td>
</tr>
</table>
<div>
<table class="esriLegendLayerLabel">
<tr>
<td>Code - table.esriLegendLayerLabel</td>
</tr>
</table>
<table class="esriLegendLayer">
<tr>
<td>Code of the table that I need to hide</td>
</tr>
</table>
<table class="esriLegendLayer">
<tr>
<td>Code - table.esriLegendLayer</td>
</tr>
</table>
</div>
</div>
</div>
See https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
An example for you would be
var layers = document.querySelectorAll('.esriLegendLayer');
Layers will be an array of the elements which have the class esriLegendLayer, you can change the selector you pass to be more or less specific as you need.
To only change the first you can use
document.querySelector('.esriLegendLayer').style.display = 'none'
You need to keep the table structure. Add tr and td to the table and the following code will work
table example
<table>
<tr>
<td>code</td>
</tr>
</table>
document.querySelectorAll("#mapLegendInside table")[2].style.display = "none";

How to remove <br> and everything after that?

If I do the following is fine:
<div id="results">
<p>Hello<br>there</p>
</div>
$($("#results p").children('br').get(0).nextSibling).remove();
I get: hello
But if I do:
<th class="infobox">Head</th>
<td>Hello<br>there</td>
var newLineRemove = $(".infobox td").children('br').get(0).nextSibling();
$wikiDOM.find(newLineRemove).remove();
Gives me
Uncaught TypeError: Cannot read property 'nextSibling' of undefined
That is because .get(...) returns a DOM element not a jQuery object.
In the first example you're using $(...) to convert that DOM element to a jQuery object but you're not doing that in the second example.
This will convert the DOM element to a jQuery element and get rid of the error
var newLineRemove = $($(".infobox td").children('br').get(0).nextSibling);
But it won't do what you want it to do because as #Forty3 said "the <td> isn't inside the ..infobox"
This seems to work but I've probably made things more complicated then they have to be:
$(function(){
var td = $(".infobox").next();
if(td.find("br").length){
$(td.contents().get().reverse()).each(function(){
$(this).remove();
if(this.tagName == "BR"){
return false;
}
});
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th class="infobox"></th>
<td>Hello<br>there</td>
</table>
I've simplest solution for this, try this one:
$('td').each(function() {
$(this).html($(this).html().split('<br>')[0]);
});
li {
margin-bottom: 10px;
}
#usp-custom-3 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
<tr>
<th class="infobox"></th>
</tr>
<tr>
<td>Hell
<br>there</td>
</tr>
<tr>
<td>Hello
<br>there<br>there</td>
</tr>
</table>
Your code doesn't work because the ".infobox td" selector is looking for a td element inside an .infobox element, but in your HTML the td immediately follows the .infobox.
If you want something that is very similar to your existing JS but working with that HTML (noting that td and th elements need to be inside a tr in a table) you can do this:
$($(".infobox").next().children("br")[0].nextSibling).remove()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr>
<th class="infobox"></th>
<td>Hello<br>there</td>
</tr>
</table>
That is, use .next() to get the element following the .infobox, get that element's child br elements, take the first one's .nextSibling, then wrap it in a jQuery object so that you can call .remove().
EDIT: Note that if there were multiple rows with similar elements the above code would only do the removal on the first one. If it were my code I would probably select all of the relevant elements and then update their HTML something more like this:
$(".infobox").next("td").html(function(i, h) { return h.split('<br>')[0] })

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');
}
});

Categories

Resources