javascript navigating child elements in this context saved to var - javascript

suppose I have the following html
<div class="mytable">
<table>
<tbody>
<tr>
</tr>
</tbody>
<table>
</div>
<div class="mytable">
<table>
<tbody>
<tr>
</tr>
</tbody>
<table>
</div>
which I address with the following code:
$('.mytable').each(function(){
var that = $(this);
});
Now I need to get tr elements inside my tables. How can I do that? I tried something like:
$(that+'>tr')
but it obviously did not work(( Any help would be appreciated. Thank you.

In reference to #NenadVracar comment you can try using:
$('.mytable').each(function(){
var that = $(this);
var $tr = that.find('tr');
});

$('div > tr') would work if tr was a direct child of div, which is obviously not the case...
In your question, you talk about context. This word is actually appropriate in jQuery because it is a formal concept of the library.
.find() is a valid solution, of course. However, you could simplify even more using the optional context parameter of the jQuery function. If you do not see what I mean, look at this code:
$('tr', '.mytable').each(function () {
var $tr = $(this);
console.log($tr.attr('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mytable">
<table>
<tbody>
<tr id="tr1"></tr>
</tbody>
</table>
</div>
<div class="mytable">
<table>
<tbody>
<tr id="tr2"></tr>
</tbody>
</table>
</div>
$('tr', '.mytable') means that you want to select tr elements within .mytable elements. If you only need tr elements from your tables, this is a decent alternative to .find().

Related

Iterating through table rows (tr) and selecting rows without a specific class in JQuery

What I am trying to do is, to be able to select rows which do not have a specific class name, and push them into a new array. I know that there is :not() Selector and .not() method to help me with this.
But the big problem is that I can't use :not() Selector with $(this) and tried using .not() method but couldn't get anywhere.
Here is my code:
$(document).ready(function(){
$('#getRows').on('click', function() {
var temp = new Array();
$('#tbl tr').each(function(){
var clsFree = $(this).not(document.getElementsByClassName("testCls"));
temp.push(clsFree);
});
console.log(temp.length);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="getRows">Get rows without class</button>
<table id="tbl">
<tr class="testCls"><td>Test1</td></tr>
<tr class="testCls"><td>Test2</td></tr>
<tr><td>Test3</td></tr>
<tr class="testCls"><td>Test4</td></tr>
<tr class="testCls"><td>Test5</td></tr>
<tr class="testCls"><td>Test6</td></tr>
<tr><td>Test7</td></tr>
<tr class="testCls"><td>Test8</td></tr>
<tr class="testCls"><td>Test9</td></tr>
</table>
Please note that the main goal here is to find rows that don't have a class name with testCls and push them into a new array. Any other method is also appreciated.
Try :not() as part of the selector in .each iterator to iterate over only with the selected rows in the selector:
$('#tbl tr:not(.testCls)').each(function(){
Working Code Snippet:
$(document).ready(function(){
$('#getRows').on('click', function() {
var temp = new Array();
$('#tbl tr:not(.testCls)').each(function(){
var clsFree = this;
temp.push(clsFree);
});
console.log(temp.length);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="getRows">Get rows without class</button>
<table id="tbl">
<tr class="testCls"><td>Test1</td></tr>
<tr class="testCls"><td>Test2</td></tr>
<tr><td>Test3</td></tr>
<tr class="testCls"><td>Test4</td></tr>
<tr class="testCls"><td>Test5</td></tr>
<tr class="testCls"><td>Test6</td></tr>
<tr><td>Test7</td></tr>
<tr class="testCls"><td>Test8</td></tr>
<tr class="testCls"><td>Test9</td></tr>
</table>
two things:
this is the syntax for the .not: $(this).not('.testCls');
clsFree is going to be a jQuery, and jQuerys still exist even if there are no elements in them. You have to check the length to see if there are any elements.
also as an aside, you might end up being happier with something like this:
$('#tbl tr:not(.testCls)').each...
$(document).ready(function() {
$('#getRows').on('click', function() {
var temp = new Array();
$('#tbl tr').each(function() {
clsFree = $(this).not('.testCls');
if (clsFree.length > 0)
temp.push(clsFree);
});
console.log(temp.length);
});
console.log('other method', $('#tbl tr:not(.testCls)').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="getRows">Get rows without class</button>
<table id="tbl">
<tr class="testCls"><td>Test1</td></tr>
<tr class="testCls"><td>Test2</td></tr>
<tr><td>Test3</td></tr>
<tr class="testCls"><td>Test4</td></tr>
<tr class="testCls"><td>Test5</td></tr>
<tr class="testCls"><td>Test6</td></tr>
<tr><td>Test7</td></tr>
<tr class="testCls"><td>Test8</td></tr>
<tr class="testCls"<td>Test9</tr></tr>
</table>

Get all global attribute values within an Id, tbody, tr, title

Using pure javascript
My code
<div id="all-items">
<table>
<tbody>
<tr title="Text 1"></tr>
<tr title="Text 2"></tr>
<tr title="Text 3"></tr>
</tbody>
</table>
</div>
I know with jQuery I can use
$("#all-items table tbody tr").title
will return
"Text 1"
but jQuery isn't working with my front end framework I'm using for some reason. In addition, I want to return all the values of the title attributes on the page within table rows.
using javascript only...
var rows = document.getElementById('all-items').getElementsByTagName('tr')
var titles = [];
for (var i = 0; i < rows.length; i++) {
titles.push(rows[i].getAttribute("title"));
}
console.log(titles);
<div id="all-items">
<table>
<tbody>
<tr title="Text 1"></tr>
<tr title="Text 2"></tr>
<tr title="Text 3"></tr>
</tbody>
</table>
</div>
The #WalksAway answer is fine. If you would like to reuse your jQuery selector though, you might look at querySelectorAll() as well.
var items = Array.from(document.querySelectorAll("#all-items table tbody tr"));
var titles = items.map(function(item) { return item.title; });
console.log(titles);
<div id="all-items">
<table>
<tbody>
<tr title="Text 1"></tr>
<tr title="Text 2"></tr>
<tr title="Text 3"></tr>
</tbody>
</table>
</div>

how to limit closest() to traverse only one row

I have a table on which if I click any row it is supposed to return the row "id" number.I have used closest() function.But the issue is the closest() selects all the "tr" below it. Is there any way to limit the function to traverse only one row data.
For example my table
<tr id="0">
<td>data0</td>
</tr>
<tr id="1">
<td>data1</td>
</tr>
<tr id="2">
<td>data2</td>
</tr>
<tr id="3">
<td>data3</td>
</tr>
<tr id="4">
<td>data4</td>
</tr>
If I click the third row that is id=2, it should return only that individual id and td(data2).
This is the code that I am trying as for now.
$("#myTable tr").click(function(){
trid = $(this).closest('tr').attr('id');
alert(trid);
return trid;
});
I have tried using next() or find() but I end up getting the Undefined error.Thanks.
I think you have misunderstood the concept of .closest(). It traverses up to the parents upward, while .find() traverses downwards to the children/grandchildren.
So as per your code it seems that you want to have the id of the clicked element. then you can just do this:
trid = this.id;
as in your code this refers to the tr you are clicking on.
Note:
Just noticed that you are using a global var named trid because it does not have the var keyword. So if you have accidently used it then you can add var trid like this in the above code.
$(document).on('click', 'td', function() {
var result = $(this).closest('tr').attr('id');
alert(result);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr id="0">
<td>data0</td>
</tr>
<tr id="1">
<td>data1</td>
</tr>
<tr id="2">
<td>data2</td>
</tr>
<tr id="3">
<td>data3</td>
</tr>
<tr id="4">
<td>data4</td>
</tr>
</table>
Try this
$("#myTable tr").click(function(){
trid = $(this).attr('id');
alert(trid);
//if you want to get to the td of it
var tdVal = $(this).find('td').html();
});
by clicking on tr, you do not need to use .closest() to access its id, just get its id using the .attr('id')or .prop('id') or even simply .id as follows:
$("#myTable tr").click(function(){
trid = $(this).attr('id');
alert(trid);
});

Two different html tables highlight the same rows order

I have a question, I am trying to make some manipulation with html tables. I have two tables,
and when I hover first row from the first table, it should highlight both rows from both tables.
I have found a solution, in making this simple function:
<script type="text/javascript">
function matchrow(){
document.getElementById('row1').style.backgroundColor='#f5f5f5';
}
function unmatchrow(){
document.getElementById('row1').style.backgroundColor='white';
}
</script>
On the first table I have:
<tr onmouseover="matchrow()" onmouseout="dismatchrow()" >
on the second table I have:
<tr id="row1" >
So when I put mouseover the first row from the first table, the first row from the second table highlights.
My question is, how to make it for the every single row, especially if it will be dynamic table.
Hope I was clear.
I've implemented this with jQuery. It doesn't use obtrusive JS and doesn't require additional IDs for rows.
Also, CSS classes are more preferable than inline styles.
HTML:
<table id="t1">
<tr><td>......</td></tr>
<tr><td>......</td></tr>
</table>
<br/>
<table id="t2">
<tr><td>......</td></tr>
<tr><td>......</td></tr>
</table>
CSS:
tr.active > td
{
background-color:#f00;
}
JS:
$(function(){
$("#t1 tr").hover(
function(){
$(this).addClass('active');
$('#t2 tr:eq(' + $('#t1 tr').index($(this)) + ')').addClass('active');
},
function(){
$(this).removeClass('active');
$('#t2 tr:eq(' + $('#t1 tr').index($(this)) + ')').removeClass('active');
}
);
});
Here is live fiddle: http://jsfiddle.net/keaukraine/KBEhA/1/
You can use the div id as a parameter in the function
<tr onmouseover="matchrow('row1')" onmouseout="dismatchrow('row1')">
function matchrow(divid){
document.getElementById(divid).style.backgroundcolor='#F5F5F5';
}
function dismatchrow(divid){
document.getElementById(divid).style.backgroundcolor='white';
}
You can use jQuery for this.
Use the .eq() and .index() functions.
A way of doing it:
HTML:
<table border="1">
<tr>
<td>Row1</td>
</tr>
<tr>
<td>Row2</td>
</tr>
<tr>
<td>Row3</td>
</tr>
<tr>
<td>Row4</td>
</tr>
</table>
<table border="1">
<tr>
<td>Row1</td>
</tr>
<tr>
<td>Row2</td>
</tr>
<tr>
<td>Row3</td>
</tr>
</table>
JS:
$('table tr').hover(function()
{
var index = $(this).index();
$('table').each(function()
{
$(this).find('tr').eq(index).css('color', 'red');
});
});
A working example can be found here.

How to tell which row number is clicked in a table?

I have a table like the following:
<table>
<tr>
<td>1</td><td>1</td><td>1</td>
</tr>
<tr>
<td>2</td><td>2</td><td>2</td>
</tr>
<tr>
<td>3</td><td>3</td><td>3</td>
</tr>
</table>
When a user clicks on the table, how can I get the index of this row (tr element)?
For example, when I click on the first tr (with 1s in the above table), it should pick it up and return 1.
This would get you the index of the clicked row, starting with one:
$('#thetable').find('tr').click( function(){
alert('You clicked row '+ ($(this).index()+1) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="thetable">
<tr>
<td>1</td><td>1</td><td>1</td>
</tr>
<tr>
<td>2</td><td>2</td><td>2</td>
</tr>
<tr>
<td>3</td><td>3</td><td>3</td>
</tr>
</table>
If you want to return the number stored in that first cell of each row:
$('#thetable').find('tr').click( function(){
var row = $(this).find('td:first').text();
alert('You clicked ' + row);
});
A better approach would be to delegate the event, which means catching it as it bubbles to the parent node.
delegation - overview
This solution is both more robust and efficient.
It allows the event to be handled even if more rows are dynamically added to the table later, and also results in attaching a single event handler to the parent node (table element), instead of one for each child node (tr element).
Assuming that the OP's example is a simplified one, the table's structure can be more complex, for example:
<table id="indexedTable">
...
<tr>
<td><p>1</p></td>
<td>2</td>
<td><p>3</p></td>
</tr>
</table>
Therefore, a simplistic approach such as getting e.target.parentElement will not work, as clicking the internal <p> and clicking the center <td> will produce different results.
Using delegation normalizes the event handling, only assuming that there are no nested tables.
implementation
Both of the following snippets are equivalent:
$("#indexedTable").delegate("tr", "click", function(e) {
console.log($(e.currentTarget).index() + 1);
});
$("#indexedTable").on("click", "tr", function(e) {
console.log($(e.currentTarget).index() + 1);
});
They attach a listener to table element and handle any event that bubbles from the table rows. The current API is the on method and the delegate method is legacy API (and actually calls on behind the scenes).
Note that the order of parameters to both functions is different.
example
A comparison between direct handler attachment and delegation is available below or on jsFiddle:
$("#table-delegate").on("click", "tr", function(e) {
var idx = $(e.currentTarget).index() + 1;
$("#delegation-idx").text(idx);
console.log('delegated', idx);
});
$("#table-direct tr").on("click", function(e) {
var idx = $(e.currentTarget).index() + 1;
$("#direct-idx").text(idx);
console.log('direct', idx);
});
$('[data-action=add-row]').click(function(e) {
var id = e.target.dataset.table;
$('#' + id + ' tbody')
.append($('<tr><td>extra</td><td>extra</td><td>extra</td></tr>')[0])
});
tr:hover{
background:#ddd;
}
button.add-row {
margin-bottom: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<h1>Event handling test</h1>
<p>Add rows to both tables and see the difference in handling.</p>
<p>Event delegation attaches a single event listener and events related to newly added children are caught.</p>
<p>Direct event handling attaches an event handler to each child, where children added after the inital handler attachment don't have a handler attached to them, and therefore their indices won't be logged to console.</p>
<h2>Delegation</h2>
<p><span>row index: </span><span id="delegation-idx">unknown</span></p>
<button class="add-row" data-action="add-row" data-table="table-delegate">Add row to delegation</button>
<table id="table-delegate" class="table">
<tbody>
<tr>
<td>normal</td>
<td>normal</td>
<td>normal</td>
</tr>
<tr>
<td><p>nested</p></td>
<td><p>nested</p></td>
<td><p>nested</p></td>
</tr>
<tr>
<td>normal</td>
<td>normal</td>
<td><p>nested</p></td>
</tr>
</table>
<h2>Direct attachment</h2>
<p><span>row index: </span><span id="direct-idx">unknown</span></p>
<button class="add-row" data-action="add-row" data-table="table-direct">Add row to direct</button>
<table id="table-direct" class="table">
<tbody>
<tr>
<td>normal</td>
<td>normal</td>
<td>normal</td>
</tr>
<tr>
<td><p>nested</p></td>
<td><p>nested</p></td>
<td><p>nested</p></td>
</tr>
<tr>
<td>normal</td>
<td>normal</td>
<td><p>nested</p></td>
</tr>
</tbody>
</table>
Here's the demo on jsFiddle.
P.S:
If you do have nested tables (or, in the general case, wish to delegate to elements with specific depth), you can use this suggestion from the jQuery bug report.
A simple and jQuery free solution:
document.querySelector('#elitable').onclick = function(ev) {
// ev.target <== td element
// ev.target.parentElement <== tr
var index = ev.target.parentElement.rowIndex;
}
Bonus: It works even if the rows are added/removed dynamically
You can use object.rowIndex property which has an index starting at 0.
$("table tr").click(function(){
alert (this.rowIndex);
});
See a working demo
$('tr').click(function(){
alert( $('tr').index(this) );
});
For first tr, it alerts 0. If you want to alert 1, you can add 1 to index.
In some cases we could have a couple of tables, and then we need to detect click just for particular table. My solution is this:
<table id="elitable" border="1" cellspacing="0" width="100%">
<tr>
<td>100</td><td>AAA</td><td>aaa</td>
</tr>
<tr>
<td>200</td><td>BBB</td><td>bbb</td>
</tr>
<tr>
<td>300</td><td>CCC</td><td>ccc</td>
</tr>
</table>
<script>
$(function(){
$("#elitable tr").click(function(){
alert (this.rowIndex);
});
});
</script>
DEMO

Categories

Resources