davewhirlwind
davewhirlwind

Reputation: 207

JavaScript to create table row spans on the fly?

Looking to table a raw table and find all identical adjacent row cells and create a row span for it using Javescript.

found this code in this SO. How to modify attribute ROWSPAN with jQuery?

    function modifyTableRowspan(column) {
    
        var prevText = "";
        var counter = 0;
    
        column.each(function (index) {
    
    
            var textValue = $(this).text();
    
            if (index === 0) {
                prevText = textValue;
            }
    
            if (textValue !== prevText || index === column.length - 1) {
    
                var first = index - counter;
    
                if (index === column.length - 1) {
                   counter = counter + 1;
                }
    
                column.eq(first).attr('rowspan', counter);
    
    
                if (index === column.length - 1)
                {
                    for (var j = index; j > first; j--) {
                        column.eq(j).remove();
                    }
                } else {
    
                    for (var i = index - 1; i > first; i--) {
                        column.eq(i).remove();
                    }
                }
    
                prevText = textValue;
                counter = 0;
            }
    
            counter++;
    
        });
    
    }

At first seemed to do the trick very nicely. But, during testing I discovered that the last row doesn't seem to work right. See this https://jsfiddle.net/eupb0fmx/3/

Haven't been able to figure out what is going on. thanks in advance. Dave

Upvotes: 2

Views: 313

Answers (1)

Ben Stephens
Ben Stephens

Reputation: 3371

I think the problem is with the following code and the for loop with the matching condition as it doesn't take account that you only want to do it if textValue === prevText

if (index === column.length - 1) {
    counter = counter + 1;
}

var column1_2 = $('.modified_table1 td:nth-child(2)');
var column2_2 = $('.modified_table2 td:nth-child(2)');


modifyTableRowspan(column1_2);
modifyTableRowspan(column2_2);



//the function
function modifyTableRowspan(column) {

  var prevText = "";
  var counter = 0;

  column.each(function (index) {
    
    var textValue = $(this).text();

    if (index === 0) {
      prevText = textValue;
    }

    if (textValue !== prevText || index === column.length - 1) {

      var first = index - counter;
      var offset = (index === column.length - 1 && textValue === prevText) ? 1 : 0;

      counter = counter + offset;

      column.eq(first).attr('rowspan', counter);

      for (var i = index - 1 + offset; i > first; i--) {
        column.eq(i).remove();
      }

      prevText = textValue;
      counter = 0;
    }

    counter++;

  });

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table class="unmodified_table" border="1">       
    <tr><td>1</td><td>22</td></tr>
    <tr><td>2</td><td >22</td></tr>
    <tr><td>3</td><td >88</td></tr>
    <tr><td>4</td><td>22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>6</td><td>3</td></tr>
    <tr><td>7</td><td >44</td></tr>
    <tr><td>8</td><td >55</td></tr>
</table>
<br />

<table class="modified_table1" border="1">  
    <tr><td>1</td><td>22</td></tr>
    <tr><td>2</td><td >22</td></tr>
    <tr><td>3</td><td >88</td></tr>
    <tr><td>4</td><td>22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>6</td><td>3</td></tr>
    <tr><td>7</td><td >44</td></tr>
    <tr><td>8</td><td >55</td></tr>
</table>
<br />
<table class="modified_table2" border="1">  
    <tr><td>1</td><td>22</td></tr>
    <tr><td>2</td><td >22</td></tr>
    <tr><td>3</td><td >88</td></tr>
    <tr><td>4</td><td>22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>5</td><td >22</td></tr>
</table>

A cleaner (in my opinion) solution might look something like:

var column1_2 = $('.modified_table1 td:nth-child(2)');
var column2_2 = $('.modified_table2 td:nth-child(2)');

modifyTableRowspan(column1_2);
modifyTableRowspan(column2_2);

function apply_rowspan_for(column, start_index, end_index) {
  column.eq(start_index).attr('rowspan', end_index - start_index + 1);

  for(let i = start_index; i < end_index; i++) {
    column.eq(i + 1).remove();
  }
}

function modifyTableRowspan(column) {
  const change_indexes = $.makeArray(column)
    .map((cell) => $(cell).text())
    .reduce((acc, v, i, all) => all[i + 1] !== v ? acc.concat(i) : acc, []);

  change_indexes.forEach((change_index, i, { [i - 1]: last }) => {
    if(change_index - (last ?? -1) > 1)
      apply_rowspan_for(column, (last ?? -1) + 1, change_index);
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table class="unmodified_table" border="1">       
    <tr><td>1</td><td>22</td></tr>
    <tr><td>2</td><td >22</td></tr>
    <tr><td>3</td><td >88</td></tr>
    <tr><td>4</td><td>22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>6</td><td>3</td></tr>
    <tr><td>7</td><td >44</td></tr>
    <tr><td>8</td><td >55</td></tr>
</table>
<br />

<table class="modified_table1" border="1">  
    <tr><td>1</td><td>22</td></tr>
    <tr><td>2</td><td >22</td></tr>
    <tr><td>3</td><td >88</td></tr>
    <tr><td>4</td><td>22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>6</td><td>3</td></tr>
    <tr><td>7</td><td >44</td></tr>
    <tr><td>8</td><td >55</td></tr>
</table>
<br />
<table class="modified_table2" border="1">  
    <tr><td>1</td><td>22</td></tr>
    <tr><td>2</td><td >22</td></tr>
    <tr><td>3</td><td >88</td></tr>
    <tr><td>4</td><td>22</td></tr>
    <tr><td>5</td><td >22</td></tr>
    <tr><td>5</td><td >22</td></tr>
</table>

Upvotes: 2

Related Questions