Styling table according to its contents - javascript

I have the following table: http://jsfiddle.net/UfhVc/1/
I am trying to:
Get the same style on all rows who have the same ID
Highlight the differences in each on the rows with the same ID.
But right now I can't seem to figure out the logic needed for step 1). It's ok to use jQuery, I just found it easier to use plain js.
Also, I get a warning in this part of the code:
table.rows[i+1].cells[0].innerHTML

Like this?
var newColor = "#F1D0F2";
var diffColor = "#CECECE";
$('#tbl tr:gt(0)').each(function () { //Loop through the trs leaving out the header
var txt = $(this).find('td:eq(0)').text(); //get the text of the id column
var $this = $(this);
var matchingRows = $('#tbl tr').not(this).filter(function () { //get the matching rows whose id colum value is same
return $(this).find('td:eq(0)').text() == txt;
}).css('background-color', newColor); //apply css for match
matchingRows.find('td').css('background-color', function (i) { //apply background color
if ($this.find('td:eq(' + i + ')').text() != this.innerHTML) return diffColor; // to the tds of matching rows but column valud differ.
});
});
Fiddle
References:
:gt()
filter()
css()
:eq()
Edit
Based on your comment here is the update:
var allColors = ["#333333","#990099", "#1295A6", "#FFFF99"]; //Set up the colors in to an array
var diffColor = "#CECECE";
$('#tbl tr:gt(0)').each(function () {
var txt = $(this).find('td:eq(0)').text();
var $this = $(this);
if($this.is('.transformed')) //check for class transformed is present if so this has already been processed skip it.
return;
//Get the matching rows whose id column value is same
var matchingRows = $('#tbl tr').filter(function () {
return $(this).find('td:eq(0)').text() == txt;
}).css('background-color', allColors.shift()).addClass('transformed'); //Set the color and add a class to avoid latter processing
matchingRows.find('td').css('background-color', function (i) { //apply background color
var $parTd = $this.find('td:eq(' + $(this).index() + ')');
if ($.trim($parTd.text()) != $.trim(this.innerHTML)) // to the tds of matching rows but column value differ.
{
$parTd.css('background-color', diffColor);
return diffColor;
}
});
});
Fiddle

For step one:
There are a few ways you can do it, I would probably attach a class to all table cells which are of a certain type, so you can easily select them all at once for editing.
<table>
<tr>
<td class="id-cell"></td>
</tr>
</table>
Then you could simply query it with CSS like:
.id-cell {
background-color:red;
}
But you can also just use more jQuery / JavaScript to find those table cells you're looking for anyways. This fiddle uses jQuery to find all the cells which are in the "id" column, and paint the background red.
http://jsfiddle.net/8QL22/

Another way of doing it:
$("table tr:not(:first-child) td:first-child").each(function(index) {
var thisId = $(this);
$("table tr:not(:first-child) td:first-child").each(function(_index) {
if (index != _index && thisId.text() == $(this).text())
{
thisId.parent("tr").css("backgroundColor", "red");
$(this).css("backgroundColor", "red");
$(this).siblings("td").each(function(sindex) {
var other = $(thisId.siblings()[sindex]);
if (other.text() != $(this).text())
other.css("backgroundColor", "yellow");
});
}
});
});
http://jsfiddle.net/w4mvp/

Related

Search table cell text against array

I have a table with a bunch of data in it. Currently, my code compares textfield input to the data in the table. If there's a match, it will show that particular table row. Here's my code:
$(document).on('keyup','#filterText',function(){
$('.all').hide(); // hide everything
$('tfoot').hide(); // hide everything
var s = $(this).val().toLowerCase(); //get input string
if(s==''){$('.all').show(); $('tfoot').show();}; // if no input then show everything
$('#report tbody tr td').each(function(i,td) {
//go through each table cell and compare
if($(td).text().toLowerCase().indexOf(s)!==-1){
$(td).closest('tr').show(); // show table row
}
});
}); //.but_filterText
This works great. But now, I need to modify this so that a user could do multiple searches at the same time, separated by a comma. So here's what I did and nothing happens:
$(document).on('keyup','#filterText',function(){
$('.all').hide();
$('tfoot').hide();
var s = $(this).val().toLowerCase().split(',');
if(s === undefined || s.length == 0){
$('.all').show(); $('tfoot').show();
};
$('#report tbody tr td').each(function(i,td) {
if(s.indexOf($(td).text().toLowerCase())!==-1){
$(td).closest('tr').show();
}
});
}); //.but_filterText
Seems like it should work but can't get it going. What am I doing wrong. Thank you
I thinks the issue is because in the input field you type space after comma, e.g. text 1, text 2 instead of text 1,text 2
i made a small (similar to yours code) example: (in this example you can type with or without space, since it will be replaced)
$('[name="search"]').on('keyup', function() {
var $tds = $('td');
var s = this.value.toLowerCase().replace(/\,\s/,',').split(',');
// consider replacing comma+space (/\,\s/) with just a comma
// and also i would recommend using filter function for finding matches,
// it will return an array of matched elements, empty if there is no match
$tds = $tds.filter(function(i, td) {
return s.indexOf($(td).text().toLowerCase()) >=0;
});
$tds.addClass('selected');
});
Here is the jsfillde - http://jsfiddle.net/zqdbso1w/1/
UPDATE (based on your comment)
Here is the jsfillde - http://jsfiddle.net/zqdbso1w/3/
simply make second iteration to seek for a substring in haystack
$('[name="search"]').on('keyup', function() {
var $tds = $('td');
var s = this.value.toLowerCase().replace(/\,\s/,',').split(',');
$tds.removeClass('selected');
$tds.each(function() {
var text = $(this).text().toLowerCase();
var r = s.filter( function(t) {
if (!t.length) return false;
return text.indexOf(t) >= 0;
});
if (r.length) $(this).addClass('selected');
});
});
UPDATE regex should be global, and remove all spaces after all commas
Here is the jsfiddle - http://jsfiddle.net/zqdbso1w/4/

Jquery and clone tables not working

i have a 2 external jquery files one allows me to clone the last row of a table while the other should allow me to grab the id of select tag based on a class assigned to it. However it only works for the original row and does not work when i clone the rows. Any help would be greatly appreacated.
Js to clone last table row:
$(document).ready(function () {
$("#btn_AddTruck").click(function () {
var $tableBody = $('#tbl_invTruck').find("tbody"),
$trLast = $tableBody.find("tr:last"),
$trNew = $trLast.clone();
// Find by attribute 'id'
$trNew.find('[id]').each(function () {
var num = this.id.replace(/\D/g, '');
if (!num) {
num = 0;
}
// Remove numbers by first regexp
this.id = this.id.replace(/\d/g, '')
// increment number
+ (1 + parseInt(num, 10));
});
$trLast.after($trNew);
});
});
Js to get id of select tag by class:
$(document).ready(function()
{
$(function(ready){
$('.selectLp').change(function() {
//alert("working" +this.id);
var Lp_Id = this.id;
alert(Lp_Id);
});
});
})
Since you are creating clone or adding dynamically to DOM you need to change
$('.selectLp').change(function() {
to
$(document).on('change','.selectLp',function(){

How to give a unique id for each cell when adding custom columns?

I wrote following code to add a custom column to my table. but i want to add a unique id to each cell in those columns. the format should be a(column no)(cell no>)
ex :- for the column no 4 :- a41, a42, a43, ........
So please can anyone tell me how to do that. Thank You!
$(document).ready(function ()
{
var myform = $('#myform'),
iter = 4;
$('#btnAddCol').click(function () {
myform.find('tr').each(function(){
var trow = $(this);
var colName = $("#txtText").val();
if (colName!="")
{
if(trow.index() === 0){
//trow.append('<td>'+iter+'</td>');
$(this).find('td').eq(5).after('<td>'+colName+iter+'</td>');
}else{
//trow.append('<td><input type="text" name="al'+iter+'"/></td>');
$(this).find('td').eq(5).after('<td><input type="text" id="a'+iter+'" name="a'+iter+'"/></td>');
}
}
});
iter += 1;
});
});
You seem to have code that's modifying the contents of the table (adding cells), which argues fairly strongly against adding an id to every cell, or at least one based on its row/column position, as you have to change them when you add cells to the table.
But if you really want to do that, after your modifications, run a nested loop and assign the ids using the indexes passed into each, overwriting any previous id they may have had:
myform.find("tr").each(function(row) {
$(this).find("td").each(function(col) {
this.id = "a" + row + col;
});
});
(Note that this assumes no nested tables.)
try this
if(trow.index() === 0){
//trow.append('<td>'+iter+'</td>');
$(this).find('td').eq(5).after('<td id="a'+column_no+cell_no+'">'+colName+iter+'</td>');
}else{
//trow.append('<td><input type="text" name="al'+iter+'"/></td>');
$(this).find('td').eq(5).after('<td id="a'+column_no+cell_no+'"><input type="text" id="a'+iter+'" name="a'+iter+'"/></td>');
}
you just have to define and iterate the column_no and cell_no variable
When all other cells are numbered consistently (for example using a data-attribute with value rXcX), you could use something like:
function addColumn(){
$('table tr').each(
function(i, row) {
var nwcell = $('<td>'), previdx;
$(row).append(nwcell);
previdx = nwcell.prev('td').attr('data-cellindex');
nwcell.attr('data-cellindex',
previdx.substr(0,previdx.indexOf('c')+1)
+ (+previdx.substr(-previdx.indexOf('c'))+1));
});
}
Worked out in this jsFiddle

How the select the multiple Table data as per selected checkbox?

There is one data table with two rows, as per below image
When user click on 2bit it should highlight that TD in that column only. I achieved this using jQuery for one check box selection, but when multiple check box selection like 2 and 4 it should highlight both the TD.
http://jsbin.com/exazoh/edit#preview working example for single value highlight.
Code: http://jsbin.com/exazoh/2/edit
Try the following function:
jQuery(function() {
// on change of an input with a name starting with "bit-select"...
jQuery('input[name^="bit-select"]').change(function(){
var checked = this.checked,
val = this.value,
column = $(this).closest("th").index() + 1;
// for each td in the current column
jQuery("#tableData tr.data td:nth-child(" +
column + ")").each(function() {
var $td = $(this);
// does the current td match the checkbox?
if ($td.text() == val) {
if (checked)
$td.addClass("jquery-colorBG-highLight");
else
$td.removeClass("jquery-colorBG-highLight");
}
});
});
});
I had to add the value attributes to the second set of checkboxes.
Working demo: http://jsbin.com/exazoh/4/edit#preview
Or the short version, since I notice you were using .filter() originally:
jQuery(function() {
jQuery('input[name^="bit-select"]').change(function(){
var method = this.checked ? "addClass" : "removeClass",
val = this.value;
jQuery("#tableData tr.data td:nth-child("+($(this).closest("th").index()+1)+")")
.filter(function(){return $(this).text()==val;})[method]("jquery-colorBG-highLight");
});
});
Demo: http://jsbin.com/exazoh/5/edit

jQuery: Get next table cell vertically

How can I use jQuery to access the cell (td) immediately below a given cell in a traditional grid-layout html table (i.e., one in which all cells span exactly one row and column)?
I know that the following will set nextCell to the cell to the immediate right of the clicked cell because they are immediate siblings, but I am trying to retrieve the cell immediately below the clicked cell:
$('td').click(function () {
var nextCell = $(this).next('td');
});
Preferably I would like to do it without any use of classes or ids.
Try this:
$("td").click(function(){
// cache $(this);
var $this = $(this);
// First, get the index of the td.
var cellIndex = $this.index();
// next, get the cell in the next row that has
// the same index.
$this.closest('tr').next().children().eq(cellIndex).doSomething();
});
$('td').click(function () {
var index = $(this).prevAll().length
var cellBelow = $(this).parent().next('tr').children('td:nth-child(' + (index + 1) + ')')
});
index is the 0-based index of the cell in the current row (prevAll finds all the cells before this one).
Then in the next row, we find the nth-child td at index + 1 (nth-child starts at 1, hence the + 1).
How about:
$('td').click(function () {
var nextCell = $(this).parent().next().find("td:nth-child(whatever)");
});
If you want to do it without using selectors, you can do:
function getNextCellVertically(htmlCell){
//find position of this cell..
var $row = $(htmlCell).parent();
var cellIndex = $.inArray(htmlCell, $row[0].cells);
var table = $row.parent()[0];
var rowIndex = $.inArray($row[0], table.rows);
//get the next cell vertically..
return (rowIndex < table.rows.length-1) ?
table.rows[rowIndex+1].cells[cellIndex] : undefined;
}
$('td').click(function () {
var nextCell = getNextCellVertically(htmlCell);
//...
});
Not that efficiency is important here but it works out much faster to do it like this - in tests over 100,000 iterations it was 2-5 times faster than the selector based approaches.
Are there an equal number of cells in each table row? If so, you could get the "count" of the cell in question, then select the corresponding cell in the next('tr').

Categories

Resources