Merge equal table cells with jQuery

Simple html table with NxM values. The goal is to combine equal cells in a column with jQuery. Please note that there are no duplicates in one line.

I got how to hide equal cells, but is there a way to combine a cell with data with an empty cell in one?

HTML:

<table border="1" id="testTable"> <tr> <td>First</td> <td>A</td> <td>A</td> </tr> <tr> <td>First</td> <td>A</td> <td>B</td> </tr> <tr> <td>Second</td> <td>V</td> <td>S</td> </tr> <tr> <td>Third</td> <td>D</td> <td>H</td> </tr> <tr> <td>Third</td> <td>E</td> <td>E</td> </tr> </table> 

JS:

 var seenArray = {}; $('#testTable td').each(function() { var index = $(this).index(); var txt = $(this).text(); if (seenArray[index] === txt) { $(this).text(''); //I think here should be "marging" } else { seenArray[index] = txt; } }); 

jsFiddle

PS One more thing: the data is initially retrieved in a json array, then I first .parseJSON() and put the data in a table using:

 for (var i = 0; i < obj.length; i++) { tr = $('<tr/>'); tr.append("<td>" + obj[i]['columnA'] + "</td>"); tr.append("<td>" + obj[i]['columnB'] + "</td>"); tr.append("<td>" + obj[i]['columnC'] + "</td>"); $('#testTable').append(tr); } 

UPD

alFReD NSH made a good solution for 2 cells. Here is his decision. But, if there are more than two equal cells.

+8
source share
7 answers

If I understand what you mean here, this is my edited version: http://jsfiddle.net/djhU7/4/

So instead of $(this).text('') I did this:

  $($this.parent().prev().children()[index]).attr('rowspan', 2); $this.hide(); 

What I did was I set the rowspan first cell to 2. This attribute "will indicate how many lines the cell is expanding." which doubles the aforementioned cell, and I hid the cell with duplicate information so that the extra cell disappears. Note that deleting a cell will destroy the index check for the next cell. It was a quick and dirty solution, but to achieve it, you must use the rowspan attribute.

Here is another version that sets the spacing between rows when inserting cells into a table, in addition to working with 3 or more duplicate cells, it is also faster because it avoids re-rendering the table (although it can be optimized more, but I don’t think that at the moment you want to take care of this, premature optimization is the root of all evil!): http://jsfiddle.net/g7uY9/1/

 for (var i = 0; i < obj.length; i++) { tr = $('<tr/>'); addColumn(tr, 'columnA', i); addColumn(tr, 'columnB', i); addColumn(tr, 'columnC', i); $('#testTable').append(tr); } function addColumn(tr, column, i) { var row = obj[i], prevRow = obj[i - 1], td = $('<td>' + row[column] + '</td>'); if (prevRow && row[column] === prevRow[column]) { td.hide(); } else { var rowspan = 1; for (var j = i; j < obj.length - 1; j++) { if (obj[j][column] === obj[j + 1][column]) { rowspan++; } else { break; } } td.attr('rowspan', rowspan); } tr.append(td); } 
+9
source

Please find an improved response for a query with a line extension / crash. Here is my fiddle:

 function MergeGridCells() { var dimension_cells = new Array(); var dimension_col = null; var i = 1; // First, scan first row of headers for the "Dimensions" column. $("#mytable").find('th').each(function () { if ($(this).text() == 'Id') { dimension_col = i; } i++; }); // first_instance holds the first instance of identical td var first_instance = null; var rowspan=1; // iterate through rows $("#mytable").find('tr.parent-grid-row').each(function () { // find the td of the correct column (determined by the dimension_col set above) var dimension_td = $(this).find('td.parent-grid-column:nth-child(' + dimension_col + ')'); if (first_instance == null) { // must be the first row first_instance = dimension_td; } else if (dimension_td.text() == first_instance.text()) { // the current td is identical to the previous // remove the current td dimension_td.remove(); ++rowspan; // increment the rowspan attribute of the first instance first_instance.attr('rowspan', rowspan); } else { // this cell is different from the last first_instance = dimension_td; rowspan=1; } }); } 

Merge jQuery cells

+6
source

Here is the running version of carla answer :

 function SummerizeTable(table) { $(table).each(function() { $(table).find('td').each(function() { var $this = $(this); var col = $this.index(); var html = $this.html(); var row = $(this).parent()[0].rowIndex; var span = 1; var cell_above = $($this.parent().prev().children()[col]); // look for cells one above another with the same text while (cell_above.html() === html) { // if the text is the same span += 1; // increase the span cell_above_old = cell_above; // store this cell cell_above = $(cell_above.parent().prev().children()[col]); // and go to the next cell above } // if there are at least two columns with the same value, // set a new span to the first and hide the other if (span > 1) { // console.log(span); $(cell_above_old).attr('rowspan', span); $this.hide(); } }); }); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button onclick="SummerizeTable('#table1')">Summerize</button> <table id="table1" border="1" cellspacing="0" > <thead> <tr> <th>State</th> <th>City</th> <th>Street</th> </tr> </thead> <tbody> <tr> <td>VT</td> <td>Burlington</td> <td>Elm</td> </tr> <tr> <td>NY</td> <td>Manhattan</td> <td>Main</td> </tr> <tr> <td>NY</td> <td>Manhattan</td> <td>Oak</td> </tr> <tr> <td>NY</td> <td>Albany</td> <td>State</td> </tr> </tbody> </table> 
+3
source

I really liked the first Farid solution, but I needed to choose a range of rows and which columns it will be applied, so I made several modifications (including the possibility of merging more than two cells). http://jsfiddle.net/djhU7/72/

 function Merge_cells($id_table,$lin_ini,$lin_fim,$array_col=array()){ $colunas=""; for($k=0;$k<count($array_col);$k++) $colunas=$colunas . " col =='$array_col[$k]' ||"; if(count($array_col)>0) $colunas="(".substr($colunas,0,-3).") &&"; echo "<script> $('#$id_table td').each(function() { var \$this = $(this); var col = \$this.index(); var txt = \$this.text(); var row = $(this).parent()[0].rowIndex; //define the interval of lines and columns it will look at if((col==0 || col==1 || col==2) row>=firstRow && row<=lastRow){ span=1; cell_above = $(\$this.parent().prev().children()[col]); //look for cells one above another with the same text while(cell_above.text()=== txt){ //if the text is the same span+=1; //increase the span cell_above_old = cell_above; //store this cell cell_above = $(cell_above.parent().prev().children()[col]); //and go to the next cell above } //if there are at least two columns with the same value, set a new span to the first and hide the other if(span>1) { console.log(span); $(cell_above_old).attr('rowspan',span); \$this.hide(); } } }); </script>"; } 
+1
source

I have expanded the carla solution. With two functions, we can combine horizontally or vertically and exclude or include cells to combine. try a working sample. https://jsfiddle.net/bn3u63pe

 /* * merge horizontally * ex) autoMergeByCol('theTable', 2, 0, 0); */ function autoMergeByCol(tableId , rowStartIndex // zero or positive , colStart // zero or positive , colEnd // equals to colStart or greater than colStart or negative to go to the end of cols ) { /* console.log('autoMergeByCol tableId=' + tableId + ', rowStartIndex=' + rowStartIndex + ', colStart=' + colStart + ', colEnd=' + colEnd ); */ var trArr = $('#' + tableId).find('tr'); // rows array for(var rowIndex = rowStartIndex ; rowIndex < trArr.length ; rowIndex++) { var tdArr = $(trArr[rowIndex]).find('td'); // cols array of the row if(colEnd < 0) colEnd = tdArr.length - 1; // if colEnd is negative, process at the end of the cols; for(var colIndex = colStart ; colIndex < tdArr.length && colIndex <= colEnd ; colIndex++) { var span = 1; var theCell = $(tdArr)[colIndex]; if($(theCell).attr('rowspan')) {continue;} var cellNext = $($(theCell).parent().children()[colIndex + span]); while(cellNext != undefined && $(theCell).text() == $(cellNext).text() && colIndex + span <= colEnd ) { span++; cellNext.hide(); cellNext = $($(cellNext).parent().children()[colIndex + span]); } if(span > 1) $(theCell).attr('colspan', span); } } } /* * merge vertically * ex) autoMergeByCol('theTable', 2, 0, 0); */ function autoMergeByRow(tableId , rowStartIndex // zero or positive , colStart // zero or positive , colEnd // equals to colStart or greater than colStart or negative ) { /* console.log('autoMergeByRow tableId=' + tableId + ', rowStartIndex=' + rowStartIndex + ', colStart=' + colStart + ', colEnd=' + colEnd ); */ var trArr = $('#' + tableId).find('tr'); // rows array for(var rowIndex = rowStartIndex ; rowIndex < trArr.length ; rowIndex++) { var tdArr = $(trArr[rowIndex]).find('td'); // cols array of the row if(colEnd < 0) colEnd = tdArr.length - 1; // if colEnd is negative, process at the end of the cols; for(var colIndex = colStart ; colIndex < tdArr.length && colIndex <= colEnd ; colIndex++) { var span = 1; var theCell = $(tdArr)[colIndex]; if($(theCell).attr('colspan')) {continue;} var cellBelow = $($(theCell).parent().next().children()[colIndex]); while(cellBelow != undefined && $(theCell).text() == $(cellBelow).text()) { span++; cellBelow.hide(); cellBelow = $($(cellBelow).parent().next().children()[colIndex]); } if(span > 1) $(theCell).attr('rowspan', span); } } } 
+1
source
  $(document).ready(function () { SummerizeTable($('#example')); }) function SummerizeTable(table) { $(table).each(function () { $(table).find('td').each(function () { var $this = $(this); var col = $this.index(); var html = $this.html(); var row = $(this).parent()[0].rowIndex; var span = 1; var cell_above = $($this.parent().prev().children()[col]); while (cell_above.html() === html) { span += 1; cell_above_old = cell_above; cell_above = $(cell_above.parent().prev().children()[col]); } if (span > 1) { $(cell_above_old).attr('rowspan', span); $this.hide(); } }); }); } 

See a working example here .

+1
source

@carla, please do this for colspan too. I tried but. I cant

0
source

All Articles