Multiple times of input in the same text field with javascript - javascript

In this code i can only input ones. If ever there are any changes of any row of column Term4, the value of the Ave is blank. How to make it dynamic? I need help here because all my codes were only searched piece by piece until i came up with this script. I'm stuck here for days. Any help would be a blessing. This is my first input...
Sample table, output 1:
Subject | Term1 | Term2 | Term3 | Term4 | Ave
Math 81 87 81 80 82.4
Science 89 83 81 80 83.25
If i change the input in term 4, the ave column will be blank.
Sample table output 2:
Subject | Term1 | Term2 | Term3 | Term4 | Ave
Math 81 87 81 85
Science 89 83 81 80 83.25
HTML:
<tr>
<th colspan="3">Learning Areas</th>
<th colspan="2">Term 1</th>
<th colspan="2">Term 2</th>
<th colspan="2">Term 3</th>
<th colspan="2">Term 4</th>
<th>Ave</th>
</tr>
</thead>
<tbody>
#foreach($card['AllGrade'] as $subject)
{!! Form::hidden('grade_id[]',$subject['grade_id']) !!}
<tr>
<td colspan="3">{!! $subject->subject !!}</td>
<td colspan="2">{!! $subject->term_1 !!}</td>
<td colspan="2">{!! $subject->term_2 !!}</td>
<td colspan="2">{!! $subject->term_3 !!}</td>
<td colspan="2">{!! Form::text('term_4[]',$subject->term_4,['class'=>'form-control','name'=>'term_4','id'=>'term_4','value'=>'']) !!}</td>
<td colspan="2" class="aver" name ="ave" id ="ave" value=""> total</td>
</tr>
#endforeach
//javascript
<script type="text/javascript">
$("tbody tr").each(function() {
var total = 0;
var ave = 0;
var count = 1;
$(this).children('td').not(':first').not(':last').each(function () {
//"this" is the current element in the loop
var number = ($(this).children('input').length == 0) ? $(this).html() : $(this).children('input').first().val();
total += parseInt(number);
ave = total/count;
count++;
});
if('.form-control'){
$(this).on('keyup', 'td:eq( 4 ) input', function(){
$('.form-control').on("input", function() {
var dInput = this.value;
total += parseInt(dInput);
ave = total/count-1;
});
console.log(ave);
$(this).parent().next().html(ave);
});
}
$(this).children('td').last().html(ave);

To avoid that NaN issue, I made sure that changed input is taken as 0. And then recalculated average, then it works.
$("tbody tr").each(function() {
var total = 0;
var ave = 0;
var count = 1;
$(this).children('td').not(':first').not(':last').each(function () {
//"this" is the current element in the loop
var number = ($(this).children('input').length == 0) ? $(this).html() : $(this).children('input').first().val();
total += parseInt(number);
ave = total/count;
count++;
});
$(this).children('td').last().html(ave);
if('.form-control'){
$(this).on('keyup', 'td:eq( 4 ) input', function(){
$('.form-control').on("input", function() {
var dInput = parseInt(this.value);
if(!dInput || dInput === NaN) {
dInput = 0;
}
var total = 0;
var count = 1;
$(this).parent().siblings().not(':first').not(':last').each(function () {
//"this" is the current element in the loop
var number = $(this).html();
total += parseInt(number);
count++;
});
total += dInput;
console.log(total);
console.log(count);
var ave = total/count;
//console.log(ave);
$(this).parent().siblings(":last").html(ave);
calcTotalave();
});
});
}
});
calcTotalave();
// calculate total average
function calcTotalave() {
var totalAve = 0;
$( ".aver" ).each(function() {
console.log($(this).html());
var thisAve = parseFloat($(this).html());
if(!thisAve || thisAve === NaN) {
thisAve = 0;
}
totalAve += thisAve;
});
console.log(totalAve);
$("#total-ave").val(totalAve);
}

Related

get the sum of 2nd column in html table

input : <table> <tr> <td>100</td> </tr> <tr> <td>200</td> </tr> </table> from the input it should return me the sum=300 instead I'm getting the output as 100200
function Save_Name()
{
var Invoice = $("#text_invoice").val();
var Name = $("#text_name").val();
var Date = $("#text_date").val();
var Amount = 0;
var n = $("table").find("tr").length;
if (n - 1 > 0)
{
for (var i = 0 ; i < n; i++)
{
var Amt = $("#table1").find("tr").eq(i).find("td").eq(2).text();
Amount += parseFloat(Amt);
}
}
}
eq starts with 0 index.The output 100200 is because it is concatenating the string instead of adding the values.Also use parseInt to convert the number from string to integer.
function Save_Name() {
var Amount = 0;
// will get all tr
var n = $("#table1 tr");
n.each(function(i, v) {
// table have only one td per tr so eq(0) will give first td
// trim is used to remove any white space
Amount += parseInt($(v).eq(0).text().trim(), 10)
})
console.log(Amount)
}
Save_Name()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table1">
<tr>
<td>100</td>
</tr>
<tr>
<td>200</td>
</tr>
</table>
Here's another way to do the same thing. Basically, I use map to create a map of integer values, then I use "get" to convert them into an array, and finally I use reduce to calculate the sum of the values in the array.
P.S.: To calculate the second column, all you need to do is to use nth-child(2) instead of nth-child(1).
$(function(){
var sum = $('#table1 tr td:nth-child(1)').map(function() {
return parseInt($(this).html(), 10)
}).get().reduce(function(a, v){
return a + v;
}, 0);
console.log(sum);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
<tr>
<td>100</td>
</tr>
<tr>
<td>200</td>
</tr>
</table>
I have alert the value of sum Amount and it is equal to 300 .
You were doing some mistake as eq(2) instead of eq(0)
But Here's the working snippet:
function Save_Name()
{
var Amount = 0;
var n = $('#test tr').length;
// alert(n);
if (n - 1 > 0)
{
for (var i = 0 ; i < n; i++)
{
var Amt = $("#test").find("tr").eq(i).find("td").eq(0).text();
Amount += parseFloat(Amt);
}
alert(Amount);
}
}
Save_Name();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id='test'>
<tr> <td>100 </td></tr>
<tr> <td>200 </td></tr>
</table>

Getting the sum and average in javascript

How to get the sum and average of the last column.In my code it wont get the correct value if the table has one,two and three rows.This works only on table with 4 rows.I know something wrong with my code but i cant figure it out how the loop works within .each function.
Important note:this runs with keyup event to update table data.Its not just a display.To be exact it is an update form.
Desired output
Item | value1 | value 2 | value3 |value 4 | Average
01 90 88 87 80 82.25
Total average 82.25 result of 82.25/1 number of row
if two rows
Item | value1 | value 2 | value3 |value 4 | Average
01 90 88 87 80 82.25
02 80 85 86 84 83.75
Total average 83 result of (82.25+83.75)/2 number of rows
But the result comes out with multiple loops
Here is the console.log(totalAverage)
86.25
176
264.75
353.5
442.25
86.25
176
264.75
353.5
442.25
Problem:How to suppress or skip this unnecessary values.I only need the 86.25 to display in total-ave.Note: this is only single row right now and have already incountered this miscaculation, how much more if the table has multiple rows then?
Html
<tr>
<th colspan="12"><h4>Card</h4></th>
</tr>
<tr>
<th colspan="3">Subjects</th>
<th colspan="2">First Grading</th>
<th colspan="2">Second Grading</th>
<th colspan="2">Third Grading</th>
<th colspan="2">Fourth Grading</th>
<th>Average</th>
</tr>
</thead>
<tbody>
#foreach($update_card['AllGrade'] as $subject)
{!! Form::hidden('grade_id[]',$subject['grade_id']) !!}
<tr>
<th colspan="3">{!! $subject->subject !!}</th>
<td colspan="2">{!! Form::text('term_1[]',$subject->term_1,['class'=>'form-control','name[]'=>'term_1','id[]'=>'term_1','value'=>'0']) !!}</td>
<td colspan="2">{!! Form::text('term_2[]',$subject->term_2,['class'=>'form-control','name[]'=>'term_2','id[]'=>'term_2','value'=>'0']) !!}</td>
<td colspan="2">{!! Form::text('term_3[]',$subject->term_3,['class'=>'form-control','name[]'=>'term_3','id[]'=>'term_4','value'=>'0']) !!}</td>
<td colspan="2">{!! Form::text('term_4[]',$subject->term_4,['class'=>'form-control','name[]'=>'term_4','id[]'=>'term_4','value'=>'0']) !!}</td>
<td colspan="2" class="average" id="average" value="0"> Average</td>
</tr>
#endforeach
<tr>
<th colspan="11">Total Average:</th>
<th>{!! Form::text('scholar_GPA',$update_card->scholar_GPA,['class'=>'form-control total-ave','name' => 'total-ave','id' => 'total-ave','value' => '0']) !!}</th>
</tr>
Javascript snippet
$("input").on("keyup", function(){
$("tbody tr").each(function() {
var col=1;
var tr =1;
var t = 0;
var a = 0;
$(this).children('td').not(':last').each(function () {
var number = ($(this).children('input').length == 0) ? $(this).html() : $(this).children('input').first().val();
// console.log(number);
// console.log(col);
t += parseInt(number);
// console.log(t);
a = t/col;
col++;
});
$(this).children('td').last().html(a);//last td of the row
// console.log(a);
col=1;
tr++;
});
calcTotalave();
});
// calculate total average
function calcTotalave() {
var totalAve = 0;
var tot=0;
var c = 2;
var count =0;
$( ".average" ).each(function() {
// console.log($(this).html());
var thisAve = parseFloat($(this).html());
if(!thisAve || thisAve === NaN || thisAve == "") {
thisAve = 0;
}
totalAve += thisAve;
//alert('count'+thisAve+totalAve);
console.log(totalAve);
count++;
});
c++;
totalAve = totalAve/c;
// console.log(totalAve);
$("#total-ave").val(totalAve);
}
UPDATED: fiddle below with comments, press space-bar to run, based around the below function.
the fiddle is made to cycle through and calc cells by row, so no .average class required. You will need to adapt it for your html table layouts as per your database output.
calcTotalave();
});
// calculate total average
function calcTotalave() {
var totalAve = 0;
$( ".average" ).each(function() {
var thisAve = parseFloat($(this).text()) || 0; // always return a number
totalAve += thisAve;
});
var Aver = totalAve / $('.average').length;
console.log(totalAve);
$("#total-ave").text(Aver);
}
instead of classing each cell as .average you could use the selector to target all the cells td of a given row:
$('input').change(function() {
calTotalAverages(); // the magic and collect the total average
});
function calTotalAverages(){
var SumAve = 0, nums = 0; // to collect total averages and the number of rows
$('tr').each(function(i) {
if (i > 0) { // ignore the first row
var $this = $(this);
SumAve += calcRowAve($this); // add up the returned averages and run the function
nums ++; // count the rows
}
}); // cycle through each row
var sum = (SumAve / nums);
$('#total-ave').text(sum.toFixed(2)); // display the total average
return sum; // return the total average
}
// calculate total average
function calcRowAve(targetRow) {
var totalAve = 0,
targetCells = targetRow.children(),
targLength = targetCells.length - 2; // total number of values in a row
targetCells.each(function(i) {
if (i > 0 && i <= targLength) {
var thisAve = parseFloat($('input',this).val()) || parseFloat($(this).text()) || 0; // always return a number
totalAve += thisAve;
} // check to ignore the first cell and the last
});
var Aver = totalAve / targLength; // get the average
targetCells.last().text(Aver); // update the last cell of the row
return Aver; // return the average for this row
}
#total-ave {
position: fixed;
right: 2em;
top: 8em;
}
input{
width: 5em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<th>item 1</th>
<th>value 1</th>
<th>value 2</th>
<th>value 3</th>
<th>value 4</th>
<th>average</th>
</tr>
<tr>
<td>1</td>
<td>90</td>
<td>88</td>
<td>87</td>
<td>80</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>80</td>
<td>85</td>
<td>86</td>
<td>84</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td><input type='number'></td>
<td><input type='number'></td>
<td><input type='number'></td>
<td><input type='number'></td>
<td></td>
</tr>
</table>
<div id='total-ave'></div>

jQuery/Javascript compare two tables against each other

I need to compare two HTML tables' rows assuming that data in first cell can be duplicated but data in second cell is always unique. I need to find whether first cell AND second cell in table1 is the same as data in first cell AND second cell in table2 for instance:
Table1:
<Table>
<tr>
<td>123</td>
<td>321</td>
</tr>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>0</td>
<td>312</td>
</tr>
<tr>
<td>123</td>
<td>323331</td>
</tr>
</Table>
Second table:
<table>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>545</td>
<td>3122</td>
</tr>
<tr>
<td>123</td>
<td>321</td>
</tr>
</table>
The result of this should be:
123 321 - good, do nothing
545 345 - good, do nothing
545 3122 - wrong its not in table1 <-
Here's what I've got so far...
$('#runCheck').click(function(){
var firstTable = $('#firstDiv table tr');
var secondTable = $('#secDiv table tr');
$(secondTable).each(function(index){
var $row = $(this);
var secTableCellZero = $row.find('td')[0].innerHTML;
var secTableCellOne = $row.find('td')[1].innerHTML;
$(firstTable).each(function(indexT){
if ($(this).find('td')[0].innerHTML === secTableCellZero){
if ($(this).find('td')[1].innerHTML !== secTableCellOne){
$('#thirdDiv').append("first: " + secTableCellZero + " second: " + secTableCellOne+"<br>");
}
}
});
});
});
Where am I going it wrong?
Just to clarify once again:
2nd table says :
row1 - john|likesCookies
row2 - peter|likesOranges
1st table says :
row1 - john|likesNothing
row2 - john|likesCookies
row3 - steward|likesToTalk
row4 - peter|likesApples
now it should say :
john - value okay
peter - value fail.
a lot alike =VLOOKUP in excel
Check this working fiddle : here
I've created two arrays which store values in each row of tables 1 and 2 as strings. Then I just compare these two arrays and see if each value in array1 has a match in array 2 using a flag variable.
Snippet :
$(document).ready(function() {
var table_one = [];
var table_two = [];
$("#one tr").each(function() {
var temp_string = "";
count = 1;
$(this).find("td").each(function() {
if (count == 2) {
temp_string += "/";
}
temp_string = temp_string + $(this).text();
count++;
});
table_one.push(temp_string);
});
$("#two tr").each(function() {
var temp_string = "";
count = 1;
$(this).find("td").each(function() {
if (count == 2) {
temp_string += "/";
temp_string = temp_string + $(this).text();
} else {
temp_string = temp_string + $(this).text();
}
count++;
});
table_two.push(temp_string);
});
var message = "";
for (i = 0; i < table_two.length; i++) {
var flag = 0;
var temp = 0;
table_two_entry = table_two[i].split("/");
table_two_cell_one = table_two_entry[0];
table_two_cell_two = table_two_entry[1];
for (j = 0; j < table_one.length; j++) {
table_one_entry = table_one[j].split("/");
table_one_cell_one = table_one_entry[0];
table_one_cell_two = table_one_entry[1];
console.log("1)" + table_one_cell_one + ":" + table_one_cell_two);
if (table_two_cell_one == table_one_cell_one) {
flag++;
if (table_one_cell_two == table_two_cell_two) {
flag++;
break;
} else {
temp = table_one_cell_two;
}
} else {}
}
if (flag == 2) {
message += table_two_cell_one + " " + table_two_cell_two + " found in first table<br>";
} else if (flag == 1) {
message += table_two_cell_one + " bad - first table has " + temp + "<br>";
} else if (flag == 0) {
message += table_two_cell_one + " not found in first table<br>";
}
}
$('#message').html(message);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<hr>
<table id="one">
<tr>
<td>123</td>
<td>321</td>
</tr>
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>0</td>
<td>312</td>
</tr>
<tr>
<td>123</td>
<td>323331</td>
</tr>
</table>
<hr>
<table id="two">
<tr>
<td>545</td>
<td>345</td>
</tr>
<tr>
<td>545</td>
<td>3122</td>
</tr>
<tr>
<td>123</td>
<td>321</td>
</tr>
</table>
<hr>
<div id="message">
</div>
</div>
If I understand your requirements, it would be easier to read the first table and store the couples as strings: 123/321, 545/345, etc...
Than you can read the second table and remove from the first list all the rows found in both.
What remains in the list are couples that do not match.
From purely an efficiency standpoint if you loop through the first table just once and create an object using the first cell value as keys and an array of values for second cells, you won't have to loop through that table numerous times
this then makes the lookup simpler also
var firstTable = $('#firstDiv table tr');
var secondTable = $('#secDiv table tr');
var firstTableData = {}
firstTable.each(function() {
var $tds = $(this).find('td'),
firstCellData = $tds.eq(0).html().trim(),
secondCellData == $tds.eq(1).html().trim();
if (!firstTableData[firstCellData]) {
firstTableData[firstCellData] = []
}
firstTableData[firstCellData].push(secondCellData)
})
$(secondTable).each(function(index) {
var $tds = $(this).find('td');
var secTableCellZero = $tds.eq(0).html().trim();
var secTableCellOne = $tds.eq(1).html().trim();
if (!firstTableData.hasOwnProperty(secTableCellZero)) {
console.log('No match for first cell')
} else if (!firstTableData[secTableCellZero].indexOf(secTableCellOne) == -1) {
console.log('No match for second cell')
}
});
I'm not sure what objective is when matches aren't found

jQuery count of specific class an element contains

I have a table and each row in the table has one or more classes depending on the region.
Here is what my table looks like:
<table>
<thead>
<th>Title</th>
<th>Name</th>
</thead>
<tbody>
<tr class="emea apac">
<td>Testing</td>
<td>Bob</td>
</tr>
<tr class="americas">
<td>Testing2</td>
<td>Jim</td>
</tr>
<tr class="emea">
<td>Testing 3</td>
<td>Kyle</td>
</tr>
<tr class="emea americas">
<td>Testing 3</td>
<td>Kyle</td>
</tr>
<tr class="emea apac americas">
<td>Testing 3</td>
<td>Kyle</td>
</tr>
<tr class="apac">
<td>Testing 3</td>
<td>Kyle</td>
</tr>
</tbody>
I am trying to now count specifically how many rows there are where the class is equal to my condition.
For example:
How many rows have ONLY .APAC = 1
How many rows have all 3 of the possible classes? = 1
I started this jsFiddle but couldn't really think of how to approach it from this point: http://jsfiddle.net/carlhussey/gkywznnj/4/
Working from your fiddle (updated)...
$(document).ready(function () {
var apac = 0,
emea = 0,
americas = 0,
combo = 0,
all = 0;
$('table tbody tr').each(function (i, elem) {
var classes = elem.className.split(' '),
hasApac = classes.indexOf('apac') > -1,
hasEmea = classes.indexOf('emea') > -1,
hasAmericas = classes.indexOf('americas') > -1;
apac += (hasApac && !hasEmea && !hasAmericas) ? 1 : 0;
emea += (hasEmea && !hasApac && !hasAmericas) ? 1 : 0;
americas += (hasAmericas && !hasApac && !hasEmea) ? 1 : 0;
if (((hasApac && hasEmea) || (hasApac && hasAmericas) || (hasEmea && hasAmericas)) && classes.length === 2) {
combo += 1;
}
if (hasApac && hasEmea && hasAmericas) {
all += 1;
}
});
$('span[name="apac"]').text(apac);
$('span[name="emea"]').text(emea);
$('span[name="americas"]').text(americas);
$('span[name="combo"]').text(combo);
$('span[name="all"]').text(all);
});
UPDATE
I'm pretty sure jQuery's hasClass method works with IE8, so you could change the .each callback to:
function (i, elem) {
var row = $(elem),
hasApac = row.hasClass('apac'),
hasEmea = row.hasClass('emea'),
hasAmericas = row.hasClass('americas');
apac += (hasApac && !hasEmea && !hasAmericas) ? 1 : 0;
emea += (hasEmea && !hasApac && !hasAmericas) ? 1 : 0;
americas += (hasAmericas && !hasApac && !hasEmea) ? 1 : 0;
if (((hasApac && hasEmea) || (hasApac && hasAmericas) || (hasEmea && hasAmericas)) && elem.className.split(' ').length === 2) {
combo += 1;
}
if (hasApac && hasEmea && hasAmericas) {
all += 1;
}
}
Updated fiddle: http://jsfiddle.net/gkywznnj/6/
var rows = $('tr'),
class = 'americas',
counter = 0;
rows.each(function () {
//If current element have .americas increment counter
if($(this).hasClass(class)) {
counter +=1
}
});
console.log(counter);
http://jsfiddle.net/gkywznnj/8/
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
function countOnlyClass(classFindA)
{
var $trA=$('table tbody tr');
var count=0;
if(classFindA.length>0){
$trA.each(function(){
var c=0;
var m=0;
var $tr=$(this);
var classA = $tr.attr('class').split(' ');
$.each(classA,function(i,cl){
if(classFindA.indexOf(cl)>-1) c++; else m++;
})
if(c>0 && c==classFindA.length && m==0) count++;
})
}
return count;
}
function comboOnlyClass(comboCount)
{
var $trA=$('table tbody tr');
var count=0;
$trA.each(function(){
var countClass = {};
var $tr=$(this);
var classA = $tr.attr('class').split(' ');
$.each(classA,function(i,cl){
if(!cl in countClass )
countClass.cl=1;
})
if(Object.size(classA )==comboCount) count++;
})
return count;
}
var a=countOnlyClass(['apac'])
$('#apac').html(a);
var a=countOnlyClass(['emea'])
$('#emea').html(a);
var a=countOnlyClass(['americas'])
$('#americas').html(a);
var a=countOnlyClass(['apac','emea','americas'])
$('#all').html(a);
var a=comboOnlyClass(2);
$('#combo').html(a);
//var a=comboOnlyClass(1); onlu one class

Iterate over table cells, re-using rowspan values

I have a simple HTML table, which uses rowspans in some random columns. An example might look like
A | B |
---|---| C
D | |
---| E |---
F | | G
I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.
I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...
without jquery:
function tableToMatrix(table) {
var M = [];
for (var i = 0; i < table.rows.length; i++) {
var tr = table.rows[i];
M[i] = [];
for (var j = 0, k = 0; j < M[0].length || k < tr.cells.length;) {
var c = (M[i-1]||[])[j];
// first check if there's a continuing cell above with rowSpan
if (c && c.parentNode.rowIndex + c.rowSpan > i) {
M[i].push(...Array.from({length: c.colSpan}, () => c))
j += c.colSpan;
} else if (tr.cells[k]) {
var td = tr.cells[k++];
M[i].push(...Array.from({length: td.colSpan}, () => td));
j += td.colSpan;
}
}
}
return M;
}
var M = tableToMatrix(document.querySelector('table'));
console.table(M.map(r => r.map(c => c.innerText)));
var pre = document.createElement('pre');
pre.innerText = M.map(row => row.map(c => c.innerText).join('\t')).join('\n');
document.body.append(pre);
td {
border: 1px solid rgba(0,0,0,.3);
}
<table>
<tr>
<td colspan=2>A</td>
<td rowspan=2>B</td>
</tr>
<tr>
<td>C</td>
<td rowspan=3>D</td>
</tr>
<tr>
<td rowspan=2>E</td>
<td rowspan=4>F</td>
</tr>
<tr></tr>
<tr>
<td rowspan=2 colspan=2>G</td>
</tr>
<tr></tr>
<tr>
<td rowspan=3 colspan=3>H</td>
</tr>
<tr></tr>
<tr></tr>
<tr>
<td colspan=3>I</td>
</tr>
</table>
Try this:
<table id="tbl">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="2" rowspan="2">A</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
Script:
var finalResult = '';
var totalTds = $('#tbl TR')[0].length;
var trArray = [];
var trArrayValue = [];
var trIndex = 1;
$('#tbl TR').each(function(){
var currentTr = $(this);
var tdIndex = 1;
trArray[trIndex] = [];
trArrayValue[trIndex] = [];
var tdActuallyTraversed = 0;
var colspanCount = 1;
$('#tbl TR').first().children().each(function(){
if(trIndex > 1 && trArray[trIndex - 1][tdIndex] > 1)
{
trArray[trIndex][tdIndex] = trArray[trIndex - 1][tdIndex] - 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex - 1][tdIndex];
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
else
{
if(colspanCount <= 1)
{
colspanCount = currentTr.children().eq(tdActuallyTraversed).attr('colspan') != undefined ? currentTr.children().eq(tdActuallyTraversed).attr('colspan') : 1;
}
if(colspanCount > 1 && tdIndex > 1)
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex][tdIndex - 1];
colspanCount--;
}
else
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).html();
tdActuallyTraversed++;
}
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
tdIndex++;
});
trIndex++;
});
alert(finalResult);
Fiddle
i am not sure about the performance, but it works well.
what I understood with your question is: You want to split the merged cell with same value and then iterate the table simply by row.
I've created a JSFiddle that will split the merged cells with the same value. Then you'll have a table that can be iterated simply by rows to get the desired output that you specified.
See it running here http://jsfiddle.net/9PZQj/3/
Here's the complete code:
<table id="tbl" border = "1">
<tr>
<td>A</td>
<td>B</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td>D</td>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
<br>
<div id="test"> </div>
Here's the jquery that is used to manipulate the table's data.
var tempTable = $('#tbl').clone(true);
var tableBody = $(tempTable).children();
$(tableBody).children().each(function(index , item){
var currentRow = item;
$(currentRow).children().each(function(index1, item1){
if($(item1).attr("rowspan"))
{
// copy the cell
var item2 = $(item1).clone(true);
// Remove rowspan
$(item1).removeAttr("rowspan");
$(item2).removeAttr("rowspan");
// last item's index in next row
var indexOfLastElement = $(currentRow).next().last().index();
if(indexOfLastElement <= index1)
{
$(currentRow).next().append(item2)
}
else
{
// intermediate cell insertion at right position
$(item2).insertBefore($(currentRow).next().children().eq(index1))
}
}
});
console.log(currentRow)
});
$('#test').append(tempTable);
You can use this Gist. It supports all the requirements by W3C, even "rowspan=0" (which seems to be only supported by Firefox).

Categories

Resources