Jquery .find doesn't look into the father element - javascript

I was trying to clone and change all the ids of a line in a table following the answer https://stackoverflow.com/a/2977114/327247
but the code below doesn't change the first id: the row id.
The javascript is
var $clone = $("#RowPly-R1-P1");
$clone.find('[id]').each(function() {
var $th = $(this);
var newID = $th.attr('id').replace(/-P\d+$/,
function(str) { return "-P"+i; });
console.log(newID);
$th.attr('id', newID);
});
console.log($clone);
$clone.appendTo($tableToModfiy);
$clone.after($("RowPly-R1-P1"));
while the html is
<tbody id="tblPlayers">
<tr id="RowPly-R1-P1">
<td>1</td>
<td>
<div class="input-group">
............
</div>
</td>
</tr>
</tbody>
All the ids internal to the row are successfully changed.I cannot understand why find doesnt change the first ID.

Because .find() will find all the descendant elements of the clone element, not the clone element itself so the ID of the clone element is not updated.
$clone.find('[id]').addBack()
You can also try a attr('id', callback) format like
var $clone = $("#RowPly-R1-P1");
$clone.find('[id]').addBack().attr('id', function(i, id) {
return id.replace(/-P\d+$/,
function(str) {
return "-P" + i;
});
});

Related

Finding last occurrence of text

I have the following type of table in html, which is generated dynamically by php :
<tr><td>Kiss the Girls</td><td>2016-01-01</td></tr>
<tr><td>Kiss the Girls</td><td>2016-02-05</td></tr>
<tr><td>Along Came a Spider</td><td>2016-01-07</td></tr>
<tr><td>Along Came a Spider</td><td>2016-01-22</td></tr>
<tr><td>Along Came a Spider</td><td>2016-03-31</td></tr>
I would like to be able to have a dynamic display filter that would allow the user to click a box and hide all but the latest version of the manuscript. So it might look like :
<tr><td>Kiss the Girls</td><td>2016-02-05</td></tr>
<tr><td>Along Came a Spider</td><td>2016-03-31</td></tr>
At this point none of the <tr> or <td> tags have an id or a class, but I could easily add a class to the first column (e.g., <td class='bookTitle'>). There is only one table on the page and php sorts it by date already. I'm open to jQuery or native JavaScript, though I would think this would be easier with jQuery. Seems like it could be done by just grabbing the last row before it changes names, but I'm not sure how to do that. Any thoughts?
According to 'Seems like it could be done by just grabbing the last row before it changes names', this is what I've come out with:
var rows = $("table tr");
if(rows.length > 0){
var last = $(rows[0]).find('td')[0].innerText;
for(var i=1; i<rows.length; i++){
var row = $(rows[i]);
var text = row.find('td')[0].innerText;
if(text === last){
$(rows[i-1]).hide();
}
last = text;
}
}
See the Pen Finding last occurrence of text by Tan Li Hau (#tanhauhau) on CodePen.
Iterate over the tr and store in key value pair where key as td content and value as object, after get the objects from it.
var a = {}; // object for storing dom element object
$('table tr').each(function() {
a[$('td:first', this).text().trim()] = this; // update the dom element object based on the column
});
var $res = $($.map(a, function(v) {
return v; // get objects and convert to jQuery object
}));
console.log($res);
$res.css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr>
<td>Kiss the Girls</td>
<td>2016-01-01</td>
</tr>
<tr>
<td>Kiss the Girls</td>
<td>2016-02-05</td>
</tr>
<tr>
<td>Along Came a Spider</td>
<td>2016-01-07</td>
</tr>
<tr>
<td>Along Came a Spider</td>
<td>2016-01-22</td>
</tr>
<tr>
<td>Along Came a Spider</td>
<td>2016-03-31</td>
</tr>
</table>
FYI : If you want to maintain the order then the value with index and object array and set order based on that
You could iterate in reverse and remove everything you've seen before as you go:
function filterPreviousVersions ( ) {
var seen = {};
$( $('tr').get( ).reverse( ) ).each( function ( ) {
var text = $( 'td', this ).first( ).text();
if ( seen[ text ] )
$( this ).remove();
seen[ text ] = true;
} );
}
filterPreviousVersions();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr>
<td>Kiss the Girls</td>
<td>2016-01-01</td>
</tr>
<tr>
<td>Kiss the Girls</td>
<td>2016-02-05</td>
</tr>
<tr>
<td>Along Came a Spider</td>
<td>2016-01-07</td>
</tr>
<tr>
<td>Along Came a Spider</td>
<td>2016-01-22</td>
</tr>
<tr>
<td>Along Came a Spider</td>
<td>2016-03-31</td>
</tr>
</table>
If you add ids in increasing order as you add the rows,
You may use this :
var valArray = [];
$('.maindiv').each(function() {
valArray.push(parseInt($(this).attr('id'), 10));
})
valArray.sort(function(a, b) {
return a - b
})
alert("Last row : " + document.getElementById(valArray[valArray.length - 1]).innerHTML); // highest`
alert("Second last : " + document.getElementById(valArray[valArray.length - 2]).innerHTML);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="2" class="maindiv">Contents in row 2</div>
<div id="5" class="maindiv">Contents in row 5</div>
<div id="3" class="maindiv">Contents in row 3</div>
<div id="1" class="maindiv">Contents in row 1</div>
<div class="main">Contents in test row</div>
<div id="4" class="maindiv">Contents in row 4</div>
To put it all together:
Succint: (May have some performance impact for large tables with many duplicate values)
$('tr').each(function(){
$("tr :contains('" + $('td', this).first().html() + "')").last()
.parent().css('color', 'red');
});
Explanation for the succint version:-
$('tr').each(function(){ // for each row of the table
$("tr // find a child inside a tr
:contains('" // that contains the text
+ $('td', this) // present within a td of the row (in line 1)
.first().html() // at the beginning
+ "')") // Using string concat to pass variable to `contains` selector)
.last() // at the end (last occurence of text)
.parent() // invoke `parent()` to select whole row
.css('color', 'red'); // apply css to identify the desired row.
});
Verbose: (Using Set of ECMAScript6 or $.unique() to remove duplicates from the full list of names. This way, when the forEach loop at the end of the code runs, it'll iterate only one per name.)
var uniqueNames = [];
$('tr').each(function(){
uniqueNames.push($('td', this).first().html());
}); // this will return the list of names from the table
// Remove duplicates from the list of names
uniqueNames = new Set(uniqueNames); // OR: uniqueNames = $.unique(uniqueNames);
uniqueNames.forEach(function(el){
$("tr :contains('" + el + "')").last().parent().css('color', 'red');
});

Get text from closest span using jQuery

I'm looking to retrieve the text inside a HTML table that is rendered via a webgrid. The text that I want is located inside a div with the class productID. My starting reference point is in the same row but the last td with the class span2. I'm trying to use jQuery's closest() method however I'm not getting any value returned.
Please see below for a section of the rendered HTML and my jQuery function:
HTML:
<tr>
<td class="span1"><div class="productID">1</div></td>
<td class="span2">Listing</td>
<td class="span2">Full Districtution</td>
<td class="span2">$1,350.00</td>
<td class="span2">2016-01-01</td>
<td class="span2"><div title="This is my brand new title!" data-original-title="" class="priceToolTip">2016-04-30</div></td>
<td>Select</td>
</tr>
jQuery:
$(".priceToolTip").mouseover(function () {
var row = $(this).closest("span1").find(".productID").parent().find(".productID").text();
console.log("Closest row is: " + row);
});
The .closest() method looks for a match in the ancestors. So you can use it to grab the tr then look for .productID like so:
var productID = $(this).closest('tr').find('.productID').text();
Or:
var productID = $(this).parent().find('.productID').text();
Or:
var productID = $(this).siblings('.span1').find('.productID').text();
.span1 is not the closest element of .priceToolTip. Use closest("tr").find(".span1 .productID") like following.
$(".priceToolTip").mouseover(function () {
var row = $(this).closest("tr").find(".span1 .productID").text();
console.log("Closest row is: " + row);
});

Find td with specific title and get one of its attributes

I have 2 tables on my page, #seats and #wings.
Now I have to check which td inside table#seats contains a special title, then check what the value of its attr "seq" is, and finally add a class to the corresponding td intable#wings.
<table id="seats">
<tr>
<td title="" seq="1">Info</td>
<td title="Exit Row Seat" seq="2">Info</td>
<td title="" seq="3">Info</td>
</tr>
</table>
My Code so far:
$("table#seats tr td[title*='Exit Row Seat']").each(function () {
var count = $(this).attr("seq");
$("table#wings tr td:nth-child(" + count + ")").addClass('exitRow');
});
My Problem is, that I get all of the td's back, not only those with the title tag I am looking for. What do I do wrong?
Then you need to iterate all td and then read the attribute:
$("table#seats tr td").each(function () {
if($(this).attr('title') == "Exit Row Seat") {
var count = $(this).attr("seq");
$(this).addClass('exitRow');
}
});
My solution at the end:
for (var i = 0; i < allSeatTables.length; i++) {
$("td[title*='Exit']", allSeatTables[i]).each(function () {
var count = $(this).attr("seq");
$(("td:eq(" + count + ")"), allWingRow[i]).addClass("exitRow");
});
}

Highlight some rows of my table in javascript

I need to highlight some rows of my table. This highlight is based on the rows present in my response object. This object can be as follow:
<table id="ListRequests" class="table table-striped">
<tbody>
<tr id="13955">
<td>JEAN DUPONT</td>
<td>ACLIMEX SPRL</td>
</tr>
</tbody>
</table>
Here is my javascript code:
var id = $("tbody tr", response).attr('id');
var cols = $('#' + id + ' td');
cols.effect("highlight", {}, 30000);
This works fine only if my response object contains only 1 row. Now I need to be able to highlight more than 1 rows at a time. So for example with the response object below:
<table id="ListRequests" class="table table-striped">
<tbody>
<tr id="13955">
<td>JEAN DUPONT</td>
<td>ACLIMEX SPRL</td>
</tr>
<tr id="13954">
<td>MIKE GIVER</td>
<td>ARGO INTERNATIONAL CORP</td>
</tr>
</tbody>
</table>
Any idea how to adapt my javascript code for that purpose ?
If you really want to do it the way you are doing it, than you need to use each
var trs = $("tbody tr", response);
trs.each( function () {
var id = this.id,
cols = $('#' + id + ' td');
cols.effect("highlight", {}, 30000);
});
Better off returning a JSON object with ids to select.
attr returns a single value, regardless how many elements are matched by the proceeding selector.
If you want to map every selected element to an ID and return array, you need map:
var ids = $("tbody tr", response).map(function (i, e) { return $(e).attr('id'); });
Once you have your list of IDs, you can iterate over that list, and highlight the matching rows in the DOM:
ids.forEach(function (id) {
var cols = $('#' + id + ' td');
cols.effect("highlight", {}, 30000);
});
Here is a working snippet.
The idea is to scrap the ids from the response you get by looping the tr nodes, from these ids build a css selector for the nodes you are interested in, and finally highlight all them.
function highlight(response){
// retrieve the ids from the response
var ids = $(response).find("tbody tr").map(function(){
// `this` will be the trs one after the other.
// `map` will put all returned values in an array.
return this.getAttribute("id");
}).get();
// build the css selector
var selector = "#" + ids.join(",#");
// highlight the corresponding nodes
$(selector).effect("highlight", {}, 30000);
}
// Call highlight with your response example.
highlight('<table id="ListRequests" class="table table-striped"><tbody><tr id="13955"><td>JEAN DUPONT</td><td>ACLIMEX SPRL</td></tr><tr id="13954"><td>MIKE GIVER</td><td>ARGO INTERNATIONAL CORP</td></tr></tbody></table>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<table id="ListRequests" class="table table-striped">
<tbody>
<tr id="13955">
<td>JEAN DUPONT</td>
<td>ACLIMEX SPRL</td>
</tr>
<tr id="13954">
<td>MIKE GIVER</td>
<td>ARGO INTERNATIONAL CORP</td>
</tr>
<tr id="1211">
<td>OTHER ONE</td>
<td>MUSN'T BE HIGHLIGHTED</td>
</tr>
</tbody>
</table>

JQuery loop through table get ID and change values in a specific column

I have a page with 2-3 tables. In those tables I want to change the text of a specific column located in <thead> and also a value in each <td> line, and I would like to get the id from each line.
What is the fastest way to do this, performance-wise?
HTML
Table-Layout:
<table class="ms-viewtable">
<thead id="xxx">
<tr class ="ms-viewheadertr">
<th>
<th>
<tbody>
<tr class="ms-itmHover..." id="2,1,0">
<td>
<td>
<tr class="ms-itmHover..." id="2,2,0">
<td>
<td>
</table>
JavaScript
Script with that I started:
$('.ms-listviewtable').each(function () {
var table = $(this);
$table.find('tr > th').each(function () {
//Code here
});
$table.find('tr > td').each(function () {
//Code here
});
How can I get the Id? Is this there a better way to do what I want?
You can get the id of an element by calling .attr on "id" i.e. $(this).attr("id");.
In jquery the best way to get to any element is by giving it an ID, and referencing it.
I would structure it the other way around - give the table elements meaningful IDs, and then put the information that I'd like to retrieve in their class attributes.
<tr id="ms-itmHover..." class="2,2,0">
And then retrieve it as follows: $('#ms-itmHover...').attr('class');
You can get the IDs by "mapping" from table row to associated ID thus:
var ids = $table.find('tbody > tr').map(function() {
return this.id;
}).get();
You can access individual cells using the .cells property of the table row:
$table.each('tbody > tr', function() {
var cell = this.cells[i]; // where 'i' is desired column number
...
});
Go thru all tables, collect all rows and locate their identifiers by your needs:
$('table.ms-viewtable').each(function(){
$(this).find('tr').each(function(){
var cells = $(this).children(); //all cells (ths or tds)
if (this.parentNode.nodeName == 'THEAD') {
cells.eq(num).html('header row '+this.parentNode.id);
} else { // in "TBODY"
cells.eq(num).html('body row '+this.id);
}
});
});
jsfiddle

Categories