detect duplicates on rows and remove class when value is changed HTML - javascript

Good day,
I have a table that can detect duplicated row on blur and I already implemented it, the code was from stack exchange and its jsfiddle, but Im confused on how to remove the class 'duplicate' when I change the value into a unique one.
heres my html
<table class="table" id="FS-table">
<thead>
<tr>
<th width="10%">Format Code</th>
<th width="60%">Account Title</th>
<th width="30%">Accound Number</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id="rowId-1" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Cash on Hand</span></td>
<td><span class="account-number">11110</span></td>
</tr>
<tr>
<td><input id="rowId-2" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Petty Cash Fund</span></td>
<td><span class="account-number">11120</span></td>
</tr>
<tr>
<td><input id="rowId-3" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">CCash in Bank</span></td>
<td><span class="account-number">11110</span></td>
</tr>
<tr>
<td><input id="rowId-4" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Accounts Receivable - Trade</span></td>
<td><span class="account-number">11320</span></td>
</tr>
<tr>
<td><input id="rowId-5" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Allowance for Bad Debts</span></td>
<td><span class="account-number">11110</span></td>
</tr>
</tbody>
</table>
and my js:
$('input.fs-format-code').on('blur', function(){
var tableRows = $("#FS-table tbody tr");
tableRows.each(function(n){
var FsInput = $(this).find('input.fs-format-code');
var id = FsInput.attr('id');
var row = $(this).find('input.fs-format-code').val();
tableRows.each(function(n){
var id2 = $(this).find('input.fs-format-code').attr('id');
// console.log("id2: "+id2 +", "+"id :"+id);
if(id2 != id){
var row2 = $(this).find('input.fs-format-code').val();
console.log("row2 :"+row2 + ", row :"+row);
if (row2 == row)
{
$(this).addClass('duplicate');
}
else{
// $(this).removeClass('duplicate');
}
}
});
});
});
if I add the else statement it will just remove again the added 'duplicate' class, How Am I gonna do it properly so that it can properly detect duplicate values or not ? thanks for your help. If you find my question hard to understand, please let me know so I can edit it right away. Have a Good day!

You could remove all of the duplicate classes at the start of the function, and then in your inner loop you could exclude all the ones marked duplicate:
$('input.fs-format-code').on('blur', function(){
var tableRows = $("#FS-table tbody tr");
/*-- Remove All Duplicate Classes --*/
tableRows.filter(".duplicate").removeClass("duplicate");
tableRows.each(function(n){
var FsInput = $(this).find('input.fs-format-code');
var id = FsInput.attr('id');
var row = $(this).find('input.fs-format-code').val();
/* -- Exclude Duplicates -- */
tableRows.not(".duplicate").each(function(n){
var id2 = $(this).find('input.fs-format-code').attr('id');
// console.log("id2: "+id2 +", "+"id :"+id);
if(id2 != id){
var row2 = $(this).find('input.fs-format-code').val();
console.log("row2 :"+row2 + ", row :"+row);
if (row2 == row)
{
$(this).addClass('duplicate');
}
}
});
});
});
It doubt it is the most efficient method, but it is probably one of the simplest modifications to your current code.
Update Fiddle here: http://jsfiddle.net/Kcas2/70/

In order to not change your code,
There is a trick to determine witch input is same as witch another, just change if/else of your code like this:
if (row2 == row && row2 != '' && row != '')
{
$(this).addClass('duplicate'+id);
}
else{
$(this).removeClass('duplicate'+id);
}
http://jsfiddle.net/yq72tr6b/

Related

Calculate quantity where textbox is a certain value

Edit
So many good answers and all of them work! Thanks a lot guys :) I wish I could mark all of them as solved!
----
Good day
Let's say I have these 2 text inputs:
<input type="text" id="plt_quantity_sum"/> <!-- this should calculate the "#quantity" where each "#uom_value" is "PLT" -->
<input type="text" id="crt_quantity_sum"/><!-- this should calculate the "#quantity" where each "#uom_value" is "CRT" -->
Let's assume the following scenario:
<table>
<tbody>
<tr>
<th>Item Name</th>
<th id="uom_value">UOM</th>
<th id="qty">Quantity</th>
</tr>
<tr>
<td>Item 1</td>
<td id="uom_value">PLT</td>
<td id="qty">5</td>
</tr>
<tr>
<td>Item 2</td>
<td class="uom_value">PLT</td>
<td id="qty">3</td>
</tr>
<tr>
<td>Item 3</td>
<td id="uom_value">CRT</td>
<td id="qty">2</td>
</tr>
<tr>
<td>Item 4</td>
<td id="uom_value">CRT</td>
<td id="qty">3</td>
</tr>
</tbody>
</table>
<input type="text" id="plt_quantity_sum" />
<input type="text" id="crt_quantity_sum" />
What needs to happen:
When the document loads, or via a button click; the quantity of "#plt_quantity_sum" and "#crt_quantity_sum" should be calculated based on their respective quantities and "UOM" values.
Some Javascript I had in mind which should clarify what exactly needs to happen:
$(document).ready(function(){
if (document.getElementById("#uom_value").value == "PLT"){
document.getElementById("#plt_quantity_sum").value == (sum of #qty);
}
else if (document.getElementById("#uom_value").value == "CRT"){
document.getElementById("#crt_quantity_sum").value == (sum of #qty);
}
});
Thanks for reading and I would greatly appreciate any help.
You just need declare two variables crtQtySum and pltQtySum for the two sums and initialize them to 0, then loop over the tds and check if it's crt or plt and updtae your variables accordingly:
$(document).ready(function() {
var crtQtySum = 0;
var pltQtySum = 0;
$(".uom_value").each(function() {
if ($(this).text() === "CRT") {
crtQtySum += parseInt($(this).next("td.qty").text());
} else if ($(this).text() === "PLT") {
pltQtySum += parseInt($(this).next("td.qty").text());
}
});
$("#plt_quantity_sum").val(pltQtySum);
$("#crt_quantity_sum").val(crtQtySum);
});
$(document).ready(function() {
var crtQtySum = 0;
var pltQtySum = 0;
$(".uom_value").each(function() {
if ($(this).text() === "CRT") {
crtQtySum += parseInt($(this).next("td.qty").text());
} else if ($(this).text() === "PLT") {
pltQtySum += parseInt($(this).next("td.qty").text());
}
});
$("#plt_quantity_sum").val(pltQtySum);
$("#crt_quantity_sum").val(crtQtySum);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<th>Item Name</th>
<th class="uom_value">UOM</th>
<th class="qty">Quantity</th>
</tr>
<tr>
<td>Item 1</td>
<td class="uom_value">PLT</td>
<td class="qty">5</td>
</tr>
<tr>
<td>Item 2</td>
<td class="uom_value">PLT</td>
<td class="qty">3</td>
</tr>
<tr>
<td>Item 3</td>
<td class="uom_value">CRT</td>
<td class="qty">2</td>
</tr>
<tr>
<td>Item 4</td>
<td class="uom_value">CRT</td>
<td class="qty">3</td>
</tr>
</tbody>
</table>
PLT:<input type="text" id="plt_quantity_sum" readonly/></br>
CRT:<input type="text" id="crt_quantity_sum" readonly/>
Note:
I used readonly attribute with the inputs, as they're just used to display the sums so they can't be modified, but we could just used a block element for that like div or span.
You can try this code. I ve didnt test it.
var plt_count = 0;
var crt_count = 0;
$(".uom_value").each(function() {
if($(this).html === 'PLT'){
plt_count += parseInt($(this).closest('.qty').html());
}
if($(this).html === 'CRT'){
crt_count += parseInt($(this).closest('.qty').html());
}
});
$("#plt_quantity_sum").val(plt_count);
$("#crt_quantity_sum").val(crt_count);
Apart from correcting the spelling mistakes that Hamza pointed out, I'd say you should basically iterate through the elements given its class name document.getElementsByClassName('.someclass') and then store and sum the value of each one of its siblings with class '.qty'.
Then you take that value and use it to populate the input you want.
Hope that helps ;)
This can be done using so many method, this is one of them :
$(document).ready(function(){
var sum_PLT = 0, sum_CRT = 0;
$('table > tbody > tr').each(function() {
tr = $(this)[0];
cells = tr.cells;
if(cells[0].textContent != "Item Name"){//To exclude the <th>
if(cells[1].textContent == "PLT")
sum_PLT += parseInt(cells[2].textContent);
else
sum_CRT += parseInt(cells[2].textContent);
}
});
$("#plt_quantity_sum").val(sum_PLT);
$("#crt_quantity_sum").val(sum_CRT);
});
This is a working jsFiddle.
You might want to try this code.
<script>
$(document).ready(function(){
var plt_qty = 0;
var crt_qty = 0;
$('.uom_value').each(function(){
if ($(this).text() === 'PLT' ) {
plt_qty = plt_qty + parseInt($(this).parent().find('.qty').text());
}else if ($(this).text() === 'CRT' ) {
crt_qty = crt_qty + parseInt($(this).parent().find('.qty').text());
}
});
$("#plt_quantity_sum").val(plt_qty);
$("#crt_quantity_sum").val(crt_qty);
});
</script>
Note : remove class uom_value in <th class="uom_value">UOM</th>.

Get a value out of element with same variable class [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Posted a similar question, but may be this case will make more sense. Got a table with many first td's of tr having a duplicate first td in a different tr. I'm using these for identification. I want to pull a value from 2nd tr and insert it into already appended(!) td in the first tr. Here is a quick html code example
<div class="tableclass">
<table>
<tbody>
<tr>
<td>id1</td>
<td>something else</td>
<td>1</td>
</tr>
<tr>
<td>id2</td>
<td>something else</td>
<td>2</td>
</tr>
<tr>
<td>id2</td>
<td>something else</td>
<td>3</td>
</tr>
<tr>
<td>id3</td>
<td>something else</td>
<td>4</td>
</tr>
<tr>
<td>id1</td>
<td>something else</td>
<td>5</td>
</tr>
<tbody>
</table>
<div>
And here is my jquery code
$(".tableclass table tbody tr").each(function(){
$(this).append('<td class="fbctr"></td>');
var trclass = $(this).find("td:first-child").html();
$(this).addClass(trclass);
// this is where I'm having a problem
var fbctr = $(this).parent().filter(trclass).eq(2).find("td:nth-child(3)");
$(this).find(".fbctr").html(fbctr);
});
OK, your problem is that jquery .filter() works on a set of given DOM elements. So you have to first select <tr> elements and then use .filter(). In your question you are applying it on your <table>
So, Your JavaScript code will be like this:
$(".tableclass table tbody tr").each(function(){
var trclass = $(this).find("td:first-child").html();
$(this).addClass(trclass);
var fbctr = $(this).parent().find('tr').filter('.'+trclass).eq(1).find("td:nth-child(3)").html();
if(typeof fbctr !== "undefined"){
console.log(fbctr);
$(this).find(".fbctr").html(fbctr);
}
});
Update(Corrected Code):
In case you want to copy the value of first occurring element into the second occurring element, use this code:
$(".tableclass table tbody tr").each(function(){
var trclass = $(this).find("td:first-child").html();
$(this).addClass(trclass);
var elements = $(this).parent().find('tr').filter('.'+trclass);
if(elements.length > 1){
var fbctr = elements.eq(0).find("td:nth-child(3)").html();
if(typeof fbctr !== "undefined")
$(this).find(".fbctr").html(fbctr);
}
});
And in case you want to copy the value of second occurring element into the first occurring element, use this code:
$(".tableclass table tbody tr").each(function(){
var trclass = $(this).find("td:first-child").html();
$(this).addClass(trclass);
var elements = $(this).parent().find('tr').filter('.'+trclass);
var fbctr = elements.eq(1).find("td:nth-child(3)").html();
if(typeof fbctr !== "undefined")
$('.'+trclass).not(this).find(".fbctr").html(fbctr);
});
You can filter out the duplicate rows first and remove all the duplicate rows but not first, then in the first rows append the 3rd td element of the last duplicate row.
In the below solution i am also removing the duplicate rows, you can keep/remove that based on your requirement.
Here is the working solution where i have added few extra node for testing of the solution.
var rows = $(".tableclass table tbody tr")
rows.each(function() {
var trclass = $(this).find("td:first-child").html();
$(this).addClass(trclass);
var dupeRows = rows.filter("." + trclass);
rows.filter("." + trclass).not(":first").remove();
if (dupeRows.length > 1) {
rows.filter("." + trclass).first().append('<td>' + $(dupeRows[dupeRows.length - 1]).find("td:nth-child(3)").html() + '</td>');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tableclass">
<table>
<tbody>
<tr>
<td>id1</td>
<td>something else</td>
<td>1</td>
</tr>
<tr>
<td>id2</td>
<td>something else</td>
<td>2</td>
</tr>
<tr>
<td>id2</td>
<td>something else</td>
<td>3</td>
</tr>
<tr>
<td>id3</td>
<td>something else</td>
<td>4</td>
</tr>
<tr>
<td>id1</td>
<td>something else</td>
<td>5</td>
</tr>
<tr>
<td>id2</td>
<td>something else</td>
<td>5</td>
</tr>
<tr>
<td>id2</td>
<td>something else</td>
<td>8</td>
</tr>
<tbody>
</table>
<div>
;

Need to compare a certain cell in contiguous rows and find rows where the value of that cell changes

I have an html table generated dynamically from a database. Rows where a particular cell value is the same represents paired data and I want to separate those pairs with an empty row. The best way I can think of is to find where that value differs from the preceding value. Is this possible?
<table id="myTable">
<tr>
<th>Team #</th>
<th>Name</th>
<th>Age</th>
</tr>
<tbody>
<tr class="data-in-table">
<td class="id">12345</td>
<td>Tom</td>
<td>46</td>
<tr class="data-in-table">
<td class="id">12345</td>
<td>Dick</td>
<td>32</td>
<tr class="data-in-table">
<td class="id">34567</td>
<td>Harry</td>
<td>45</td>
<tr class="data-in-table">
<td class="id">76543</td>
<td>Will</td>
<td>45</td>
</tr>
<tr class="data-in-table">
<td class="id">76543</td>
<td>Sam</td>
<td>45</td>
</tr>
</tbody>
This is code I've seen comparing adjacent cells and tried to change for my needs:
$("#myTable").each(function () {
$(this).find('tr').each(function (index) {
var currentRow = $(this);
var nextRow = $(this).next('tr').length > 0 ? $(this).next('tr') : null;
if (index%2==0&&nextRow && currentRow(td[0].text() != nextRow(td[0].text()) {
$('#myTable tr:next').after('<tr><td></td><td></td><td></td></tr>');
}
});
});
I'd like it to look something like this:
Team # Name Age
12345 Tom 46
12345 Dick 32
34567 Harry 45
76543 Will 45
76543 Sam 45
As the database updates, team members will always be positioned adjacent to each other, but sometimes one teammate will appear before the second teammate and the table should reflect that.
I found that this works, through trial and error:
var last = ''
var rowCount = $('#myTable >tbody >tr').length;
for (var i=0;i<rowCount-1;i++) {
if (last != $('#myTable tr .id:eq('+i+')').html()) {
var lastRow = $('#myTable tr .id:eq('+i+')')
$(lastRow).parents('tr').before('<tr><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td></tr>')
}
var last = $('#myTable tr .id:eq('+i+')').html()
}
I don't know if there is a more efficient way than using a for.. statement to run through each row.

Modifying javascript table to search for specific data

The search form I'm using is found here: http://bootsnipp.com/snippets/featured/js-table-filter-simple-insensitive
I found a nice js search form created by Cyruxx that I am implementing on my site. Is it possible to modify this code to only search specific table headers?
For example I have:
<table class="table table-list-search">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<td>107</td>
<td>John Doe</td>
<td>1074 example street</td>
</tr>
<tr>
<td>100</td>
<td>Henry</td>
<td>1111 example ave</td>
</tr>
</tbody>
</table>
How can I modify the code to only search the id column for example. In other words, typing the number '1' would only show table rows with a '1' in the 'id' header. Typing '1074' in my example would return 0 results while typing '1' would show both listings.
$(document).ready(function() {
var activeSystemClass = $('.list-group-item.active');
//something is entered in search form
$('#system-search').keyup( function() {
var that = this;
// affect all table rows on in systems table
var tableBody = $('.table-list-search tbody');
var tableRowsClass = $('.table-list-search tbody tr');
$('.search-sf').remove();
tableRowsClass.each( function(i, val) {
//Lower text for case insensitive
var rowText = $(val).text().toLowerCase();
var inputText = $(that).val().toLowerCase();
if(inputText != '')
{
$('.search-query-sf').remove();
tableBody.prepend('<tr class="search-query-sf"><td colspan="6"><strong>Searching for: "'
+ $(that).val()
+ '"</strong></td></tr>');
}
else
{
$('.search-query-sf').remove();
}
if( rowText.indexOf( inputText ) == -1 )
{
//hide rows
tableRowsClass.eq(i).hide();
}
else
{
$('.search-sf').remove();
tableRowsClass.eq(i).show();
}
});
//all tr elements are hidden
if(tableRowsClass.children(':visible').length == 0)
{
tableBody.append('<tr class="search-sf"><td class="text-muted" colspan="6">No entries found.</td></tr>');
}
});
});
First of all - that's not great search code, its not terribly preformant and mixes view and model concerns in a way that might get difficult to maintain. I would recommend using a pre-build widget, rather than copy-pasting code that you don't understand from blogs (or wherever).
To answer your question though, you can simply constrain which columns are searchable with a css class, and use that class as a search filter:
so change
var rowText = $(val).text().toLowerCase();
to
var rowText = $(val).find('.searchable').text().toLowerCase();
and then tag everything that you want to be searchable:
<table class="table table-list-search">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<td class="searchable">107</td>
<td>John Doe</td>
<td>1074 example street</td>
</tr>
<tr>
<td class="searchable">100</td>
<td>Henry</td>
<td>1111 example ave</td>
</tr>
</tbody>
</table>

How can I get the corresponding table column (td) from a table header (th)?

I want to get the entire column of a table header.
For example, I want to select the table header "Address" to hide the address column, and select the "Phone" header to show the correspondent column.
<table>
<thead>
<tr>
<th id="name">Name</th>
<th id="address">Address</th>
<th id="address" class='hidden'>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td class='hidden'>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td class='hidden'>3456</td>
</tr>
</tbody>
I want to do something like http://www.google.com/finance?q=apl (see the related companies table) (click the "add or remove columns" link)
Something like this would work -
$('th').click(function() {
var index = $(this).index()+1;
$('table td:nth-child(' + index + '),table th:nth-child(' + index + ')').hide()
});
The code above will hide the relevant column if you click on the header, the logic could be changed to suit your requirements though.
Demo - http://jsfiddle.net/LUDWQ/
With a couple simple modifications to your HTML, I'd do something like the following (framework-less JS):
HTML:
<input class="chk" type="checkbox" checked="checked" data-index="0">Name</input>
<input class="chk" type="checkbox" checked="checked" data-index="1">Address</input>
<input class="chk" type="checkbox" checked="checked" data-index="2">Phone</input>
<table id="tbl">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td>3456</td>
</tr>
</tbody>
Javascript:
var cb = document.getElementsByClassName("chk");
var cbsz = cb.length;
for(var n = 0; n < cbsz ; ++n) {
cb[n].onclick = function(e) {
var idx = e.target.getAttribute("data-index");
toggleColumn(idx);
}
}
function toggleColumn(idx) {
var tbl = document.getElementById("tbl");
var rows = tbl.getElementsByTagName("tr");
var sz = rows.length;
for(var n = 0; n < sz; ++n) {
var el = n == 0 ? rows[n].getElementsByTagName("th")[idx] : rows[n].getElementsByTagName("td")[idx];
el.style.display = el.style.display === "none" ? "table-cell" : "none";
}
}
http://jsfiddle.net/dbrecht/YqUNz/1/
I added the checkboxes as it doesn't make sense to bind the click to the column headers as you won't be able to toggle the visibility, only hide them.
You can do something with CSS, like:
<html>
<head>
<style>
.c1 .c1, .c2 .c2, .c3 .c3{
display:none;
}
</style>
</head>
<body>
<table class="c2 c3">
<thead>
<tr>
<th id="name" class="c1">Name</th>
<th id="address" class="c2">Address</th>
<th id="phone" class="c3">Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td class="c1">Freddy</td>
<td class="c2">Nightmare Street</td>
<td class="c3">123</td>
</tr>
<tr>
<td class="c1">Luis</td>
<td class="c2">Lost Street</td>
<td class="c3">3456</td>
</tr>
</tbody>
</table>
</body>
</html>
To hide a column, you add with Javascript the corresponding class to the table. Here c2 and c3 are hidden.
You could add dynamically the .c1, .c2,... in a style tag, or define a maximum number.
The easiest way to do this would be to add a class to each td that matches the class of the header. When you click the , it checks the class, then hides every td with that class. Since only the s in that column would hide that class, it would effectively hide the column.
<table>
<thead>
<th>Name</th>
<th>Address</th>
</thead>
<tbody>
<tr>
<td class="Name">Joe</td>
<td class="Address">123 Main St.
</tbody>
</table>
And the script something like:
$('th').click( function() {
var col = $(this).html(); // Get the content of the <th>
$('.'+col).hide(); // Hide everything with a class that matches the col value.
});
Something like that, anyway. That's probably more verbose than it needs to be, but it should demonstrate the principle.
Another way would be to simply count how many columns over the in question is, and then loop through each row and hide the td that is also that many columns over. For instance, if you want to hide the Address column and it is column #3 (index 2), then you would loop through each row and hide the third (index 2).
Good luck..
Simulating the Google Finance show/hide columns functionality:
http://jsfiddle.net/b9chris/HvA4s/
$('#edit').click(function() {
var headers = $('#table th').map(function() {
var th = $(this);
return {
text: th.text(),
shown: th.css('display') != 'none'
};
});
var h = ['<div id=tableEditor><button id=done>Done</button><table><thead><tr>'];
$.each(headers, function() {
h.push('<th><input type=checkbox',
(this.shown ? ' checked ' : ' '),
'/> ',
this.text,
'</th>');
});
h.push('</tr></thead></table></div>');
$('body').append(h.join(''));
$('#done').click(function() {
var showHeaders = $('#tableEditor input').map(function() { return this.checked; });
$.each(showHeaders, function(i, show) {
var cssIndex = i + 1;
var tags = $('#table th:nth-child(' + cssIndex + '), #table td:nth-child(' + cssIndex + ')');
if (show)
tags.show();
else
tags.hide();
});
$('#tableEditor').remove();
return false;
});
return false;
});
jQuery('thead td').click( function () {
var th_index = jQuery(this).index();
jQuery('#my_table tbody tr').each(
function(index) {
jQuery(this).children('td:eq(' + th_index + ');').each(
function(index) {
// do stuff here
}
);
}
);
});
here's a working fiddle of this behaviour:
http://jsfiddle.net/tycRW/
of course, hiding the column with out hiding the header for it will have some strange results.

Categories