Skip to content Skip to sidebar Skip to footer

Merge Equal Table Cells With JQuery

Simple html table with NxM values. The aim is to merge equal cells in column with jQuery. Note, that in one row there are no duplicates. I got how to hide the equal cells, but is

Solution 1:

If I get what you mean here, this 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 the I set the rowspan of first cell to 2. This attribute "will indicates for how many rows the cell extends." which will make the above cell twice bigger, and I hid the cell with the duplicate information so the extra cell will go away. Note that removing the cell will ruin the index check for the next cell. This was a just a quick and dirty solution but rowspan attribute has to be used somewhere to achieve it.

Here's another version, that sets rowspan on the time when inserting the cells into the table, beside the fact that it works with 3 duplicate cells and more, it's also faster, because it avoids re-rendering of the table(though it can be optimized more, but I don't think at this moment you wanna care about it, 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);
}

Solution 2:

Please find the improved answer for your query with row expand/collapse. 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;
        }
    });
}

Jquery Cell Merging


Solution 3:

Here's a runnable version of carla's 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>

Solution 4:

I really liked Farid first solution, but I needed to select the range of lines and which columns it would be applied, so I made a few modifications (including the possiblity of more than 2 cells merge). 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>";
}

Solution 5:

I extended carla's solution. With two functions, we can merge horizontally or vertically and exclude or include cells to merge. try the 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);          
        }
    }
}

Post a Comment for "Merge Equal Table Cells With JQuery"