how to get the row index on TD click using jquery - javascript

I am trying to get the row no and column no of cell on which user has clicked
my code is giving the correct column no but row no always giving 0 and 1
I am using the following code
help me to find the reason why giving the row no always 0 and 1
<script>
$('td').click(function(){
col = $(this).parent().children().index($(this));
row = $(this).parent().parent().children().index($(this).parent());
alert("row no:"+row+"col no :"+col);
</script>

You can simply use $(element).index() to get that element's index within it's siblings
$('td').click(function() {
var col = $(this).index(),
row = $(this).parent().index();
console.log("row index:" + row + ", col index :" + col);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>Item 1</td>
<td>Item 2</td>
<td>Item 3</td>
<td>Item 4</td>
<td>Item 5</td>
</tr>
<tr>
<td>Item 1</td>
<td>Item 2</td>
<td>Item 3</td>
<td>Item 4</td>
<td>Item 5</td>
</tr>
<tr>
<td>Item 1</td>
<td>Item 2</td>
<td>Item 3</td>
<td>Item 4</td>
<td>Item 5</td>
</tr>
<tr>
<td>Item 1</td>
<td>Item 2</td>
<td>Item 3</td>
<td>Item 4</td>
<td>Item 5</td>
</tr>
<tr>
<td>Item 1</td>
<td>Item 2</td>
<td>Item 3</td>
<td>Item 4</td>
<td>Item 5</td>
</tr>
</table>

It is much simpler and faster without jQuery if you use .cellIndex and .rowIndex.
$('td').click(function(){
var col = this.cellIndex,
row = this.parentNode.rowIndex;
alert("row no:"+row+"col no :"+col);
As noted by #PatrickRoberts below, old Opera's behavior (version 12 and lower) deviates in that it honors the thead/tbody/tfoot order in HTML that you provide, so if you put the tfoot above the tbody (which is really where it should go), and it has one or more rows, the tbody rows will be offset by that much.
The correct behavior is to consider the thead at the top and the tbody at the bottom, irrespective of where they were defined.
This is no longer an issue in modern Opera since it now uses Chrome's Webkit fork, so the behavior is consistent.
Also note that jQuery's manual .index() calculation will only take into account the children of the given tbody, assuming that's the context here.

Related

ie11: Insert and delete html table row after a row with a class name

I'm working on a JSP page. When page renders based on certain conditions
1)I have to insert a row to an existing table which has a row with a class name "details" OR
2) delete the inserted row if it exists
Page has to render in ie11 as well. So I cannot use insertAfter() or any es6 methods. I'm unable to append/ remove at the right node
Code
<table id="myTable">
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr class="details">
<td>cell 3</td>
<td>cell 4</td>
<td>cell 1</td>
<td>cell 2</td>
</tr>
<tr>
<td>cell 7</td>
<td>cell 8</td>
<td>cell 1</td>
<td>cell 2</td>
</tr>
</table>
var newHtml = '<tr class="select__pcp"><td colspan="2"> </td><td class="txt-right">text Msg</td><td class="txt-right span2"></td></tr>';
if(condition) {
// insert newHTML after <tr class="details">
} else {
//if <tr> with class="select__pcp" exists then delete it
}
You need to use appendChild: see this page(https://www.w3schools.com/jsreF/met_node_appendchild.asp)
and removeChild: see this page(https://www.w3schools.com/JSREF/met_node_removechild.asp)
and if you add a node in special place you need to use insertAdjacentElement: see this page(https://www.w3schools.com/jsref/met_node_insertadjacentelement.asp)
To Add: You can try setting the outerHTML of the details element to include the new element.
To Remove: you can set the outerHTML to an empty string
---on snippet load: adds element to table, waits 3 seconds and removes element.
var newHtml = '<tr class="select__pcp"><td colspan="2"> </td><td class="txt-right">text Msg</td><td class="txt-right span2"></td></tr>';
function removeOrAdd(action){
if(action) {
document.querySelector('.details').outerHTML += newHtml
} else {
document.querySelector('.select__pcp').outerHTML = ''
}
}
removeOrAdd(true)
setTimeout(removeOrAdd, 3000, false)
<table id="myTable">
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr class="details">
<td>cell 3</td>
<td>cell 4</td>
<td>cell 1</td>
<td>cell 2</td>
</tr>
<tr>
<td>cell 7</td>
<td>cell 8</td>
<td>cell 1</td>
<td>cell 2</td>
</tr>
</table>

How to filter getElement based on CSS property in JS or jQuery

The following code gets all the tr tags in #mytable:
table = document.getElementById("myTable");
trs = table.getElementsByTagName("tr");
But if we want to get only tr tags whose display is not none, what should I do?
Thanks.
Not the best solution, but you can do this...
let tableRows = $("#my-table tr");
tableRows.map((i, obj)=>{
if($(obj).attr('style') != 'display: none;'){
// whatever you want to do here...
console.log(obj);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table id="my-table">
<tbody>
<tr>
<td>data 1</td>
<td>data 2</td>
</tr>
<tr style="display: none;">
<td>data 3</td>
<td>data 4</td>
</tr>
<tr>
<td>data 5</td>
<td>data 6</td>
</tr>
<tr style="display: none;">
<td>data 7</td>
<td>data 8</td>
</tr>
<tr>
<td>data 9</td>
<td>data 10</td>
</tr>
</tbody>
</table>
You can use the :visible selector which is a jquery extension (https://api.jquery.com/visible-selector/) that allows seelction of elements based on display visibility.
In the following snippet - there are 3 tr's but the middle one is hidden with display:none. The console log targets the visible tr's and logs the number (2);
$(document).ready(function(){
const totalRows = $('#myTable tr');
const visibleRows = totalRows.filter(':visible');
console.log('total rows: '+ totalRows.length); // gives 3
console.log('visible rows: '+ visibleRows.length); // gives 2 - since one tr is hidden
})
.second-row {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
<tbody>
<tr class="first-row">
<td>row 1</td>
<td>row 1</td>
<td>row 1</td>
</tr>
<tr class="second-row">
<td>row 2</td>
<td>row 2</td>
<td>row 2</td>
</tr>
<tr class="third-row">
<td>row 3</td>
<td>row 3</td>
<td>row 3</td>
</tr>
</tbody>
</table>
Simple solution with VanillaJS
var elems = document.querySelectorAll('tr');
var noneElems = [];
elems.forEach(function (element) {
if (window.getComputedStyle(element).display == 'none') {
noneElems.push(element);
}
});
console.log( { noneElems } );
<table id="mytable">
<tr>
<td>Block</td>
<td>1</td>
</tr>
<tr style="display:none">
<td>None</td>
<td>1</td>
</tr>
<tr>
<td>Block</td>
<td>2</td>
</tr>
<tr style="display:none">
<td>None</td>
<td>2</td>
</tr>
</table>

Determine number of td with specific class in each table row

I use this code to hide all rows in a table that have a td with a class named "hide". This is working fine.
$('.table').find('tr:has(td.hide)').hide();
Now I am trying to hide all all rows in table if the row has n number of td with the class equal to hide. I was not even able to loop on the tr list of the table with thos code
$('.table > tr').each(function() {
console.log("new tr", $(this).text());
});
my html looks as following
<table class='table'>
<tr class='hidable'><td class='hide'> Some text</td> <td class='hide'> Some text</td></tr>
<tr class='hidable'><td class='hide'> Some text</td> <td class='nothide'> Some text</td></tr>
</table>
in this example i want to hide the row if the two tds have the class hide.
When you create a table without tbody, that tag is automatically generated.
Child combinator:
Elements matched by the second selector must be the immediate children of the elements matched by the first selector.
Include tbody as part of the selector. Try $('.table tbody > tr')
$('.table tbody > tr').each(function() {
console.log("new tr", $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class='table'>
<tr class='hidable'>
<td> Some text </td>
<td class='hide'> Some text</td>
<td class='hide'> Some text</td>
</tr>
<tr>
<td class='nothide'> Some text</td>
</tr>
</table>
OR: Remove > from the selector
$('.table tr').each(function() {
console.log("new tr", $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class='table'>
<tr class='hidable'>
<td> Some text </td>
<td class='hide'> Some text</td>
<td class='hide'> Some text</td>
</tr>
<tr>
<td class='nothide'> Some text</td>
</tr>
</table>
With jQuery I'd suggest using toggleClass():
// here we select the <tr> elements, and chain the toggleClass() method
// to that jQuery collection:
$('tr').toggleClass(function() {
// within the anonymous function 'this' refers to the current <tr>
// element of the collection (the native DOM node not a jQuery $(this))
// we use Element.querySelectorAll() to retrieve all the <td> elements
// with a class of 'hide' and then test the length to see if there
// are more than one. If this is true, we return the 'hideRow' class
// to the method, otherwise we return an empty string. Obviously this
// approach uses a CSS selector ('hideRow') to hide the relevant <tr>
// elements:
return this.querySelectorAll('.hide').length > 1 ? 'hideRow' : '';
});
.hide {
background-color: limegreen;
opacity: 0.5;
}
.hideRow {
/* here we use opacity: 0.5 so that you can visually
see which elements are selected/affected; in production
you should obviously switch to 'display: none' to hide the
elements: */
opacity: 0.5;
}
<table>
<tbody>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td class="hide">cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td class="hide">cell 2</td>
<td>cell 3</td>
<td class="hide">cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td class="hide">cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td class="hide">cell 1</td>
<td class="hide">cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td class="hide">cell 1</td>
<td class="hide">cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
</tbody>
</table>
JS Fiddle demo.
In native JavaScript — using a contemporary browser — the following would achieve the same thing:
// here we use the spread syntax to conver the iterable NodeList returned by
// document.querySelectorAll() into an Array, we then iterate over that Array
// of Nodes using Array.prototype.forEach():
[...document.querySelectorAll('tr')].forEach(
// we use an anonymous Arrow function - as we don't need to use 'this' - in
// order perform a function on each of the <tr> elements of the Array of
// <tr> elements; the 'tr' passed into the function is a reference to the
// current <tr>:
(tr) => {
// here we use the Element.classList API, with its toggle() method to
// supply a class-name ('hideRow'), and we use the assessment to determin
// whether or not the class-name should be applied. If the assessment
// evaluates to true then the class-name is applied, if false it is not:
tr.classList.toggle('hideRow', tr.querySelectorAll('.hide').length > 1);
});
.hide {
background-color: limegreen;
opacity: 0.5;
}
.hideRow {
opacity: 0.5;
}
<table>
<tbody>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td class="hide">cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td class="hide">cell 2</td>
<td>cell 3</td>
<td class="hide">cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td class="hide">cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td class="hide">cell 1</td>
<td class="hide">cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td class="hide">cell 1</td>
<td class="hide">cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
<tr>
<td>cell 1</td>
<td>cell 2</td>
<td>cell 3</td>
<td>cell 4</td>
</tr>
</tbody>
</table>
JS Fiddle demo.
As an important addenda to my original answer, the reason that your selector:
$('.table > tr')
doesn't work is because of the child combinator, the >, which would cause jQuery to retrieve the <tr> elements which are children of the <table class=".table"> element. As browsers predictably rescue 'broken' HTML — though a <tbody> is not mandatory according to the spec — they will all automagically insert a <tbody> element to wrap any <tr> elements which are contained within a <table> that aren't already so wrapped.
This has been discussed elsewhere on the site: https://stackoverflow.com/a/5568877/82548
References:
JavaScript:
Array.prototype.forEach().
Arrow functions ((arguments) => { ...statements... }.
document.querySelectorAll().
Element.classList API.
Element.querySelectorAll().
NodeList.prototype.forEach().
Spread (...) syntax.
jQuery:
toggleClass().
You want to hide row if 2 td's have hide class , if this is your requirement then here is tested example
$(".table tr").each(function(){
if($(this).find("td.hide").length == 2) {
$(this).hide();
}
});
Here I loop through each tr and then in each tr I check all td with class "hide" with find("td.hide").length == 2 and if length is equal to two then hide the row.

How to construct this kind of irregular tables with colspan and rowspan?

I need to construct a table which will have complex col and row. How can I construct this kind of table?
I've already tried to construct but it seems that the output is not what I wished for. I want to make a left header which span two rows and the rows will have header and input field.
This is my code that I've already tried. I failed whenever i try to put theader to all the fields.
<table>
<tr>
<td rowspan="2">Flock ID</td>
<td>Field 1</td>
<td>Field 2</td>
<td>Field 3</td>
<td>Field 4</td>
<td>Field 5</td>
</tr>
<tr>
<td>Field 6</td>
<td>Field 7</td>
<td>Field 8</td>
<td>Field 9</td>
<td>Field 10</td>
</tr>
</table>
The table should have a columnn that span two rows. For each row there will be several headers.
This the example pic of my expected table

Swapping td elements of table using javascript

Is there a simple way of swapping elements of an html table using javascript?
for instance having a table like this:
<table>
<tr>
<td class = "draggable">
<div class = "droppable">Item 1</div>
</td>
</tr>
<tr>
<td class = "draggable">
<div class = "droppable">Item 2</div>
</td>
</tr>
I want to make it available to swap cells.
Thanks!
I've written a little function to swap elements. Pass as arguments the parent (container of swapping elements), and two numbers (index) of the children elements that you want to be swapped.
var rowsParent = document.getElementById('sortRows');
var cellsParent = document.getElementById('sortCells');
swapElements(rowsParent,0,1);
swapElements(cellsParent,2,0);
function swapElements(parent,elemA,elemB){
//a little of validation
if(!parent||parent.constructor.toString().search('HTML')===-1) return;
var children = parent.children;
if(typeof elemA!=='number' || typeof elemB!=='number' || elemA===elemB || !children[elemA] || !children[elemB]) return;
elemB = elemA<elemB ? elemB--:elemB;
var childNumb = children.length - 1;
var a = parent.removeChild(children[elemA]);
var b = parent.removeChild(children[elemB]);
append(elemB,a);
append(elemA,b);
function append(a,b){
childNumb===a ? parent.appendChild(b) : parent.insertBefore(b,children[a]);
}
}
table, td {
border: solid 1px black;
padding: 3px;
margin: 15px;
}
<table>
<tbody id="sortRows">
<tr>
<td>a 1</td>
<td>a 2</td>
<td>a 3</td>
<td>a 4</td>
<td>a 5</td>
</tr>
<tr id="sortCells">
<td>b 1</td>
<td>b 2</td>
<td>b 3</td>
<td>b 4</td>
<td>b 5</td>
</tr>
<tr>
<td>c 1</td>
<td>c 2</td>
<td>c 3</td>
<td>c 4</td>
<td>c 5</td>
</tr>
<tr>
<td>d 1</td>
<td>d 2</td>
<td>d 3</td>
<td>d 4</td>
<td>d 5</td>
</tr>
<tr>
<td>e 1</td>
<td>e 2</td>
<td>e 3</td>
<td>e 4</td>
<td>e 5</td>
</tr>
</tbody>
</table>
You could do it in the same way you swap contents for any variable:
var child1_HTML = $("table tr:nth-child(1)").html();
$("table tr:nth-child(1)").html($("table tr:nth-child(2)").html());
$("table tr:nth-child(2)").html(child1_HTML);

Categories

Resources