ESS
ESS

Reputation: 175

jQuery to transpose HTML table with header and footer

I need to transpose an HTML table (swap rows and columns). I found numerous jQuery plugins but they are more than what I need.

I adapted some neat jQuery code from this stack but it does not work on tables that include thead and tfoot elements.

function tableTransform(objTable) {
    objTable.each(function () {
        var $this = $(this);
        var newrows = [];
        $this.find("tr").each(function () {
            var i = 0;
            $(this).find("td").each(function () {
                i++;
                if (newrows[i] === undefined) {
                    newrows[i] = $("<tr></tr>");
                }
                newrows[i].append($(this));
            });
        });
        $this.find("tr").remove();
        $.each(newrows, function () {
            $this.append(this);
        });
    });

    return false;
}

I created the fiddle below that provides an example of the markup and the code. Can someone update the function so it supports thead and tfoot elements?

http://jsfiddle.net/4tobvo05/4/

Just like the existing code, the new code must maintain the class and style values on each td as well as the table itself so the CSS is applied properly. It also needs to fixup the tfoot so it contains the correct number td cells that wrap a non-breaking space.

Upvotes: 3

Views: 5192

Answers (2)

Mehul Shah
Mehul Shah

Reputation: 1

This code will work with row and colspan as well.

jQuery("#table1").each(function() {
  var jthis = jQuery(this);
  var newrows = [];
  var row = 0;
  jthis.find("tr").each(function(){
    row++;
    var col = 0;
    var prev_colspan = 0;
    var prev_rowspan = 0;
    var row_count = 0;
    jQuery(this).find("td").each(function(){
      col++;
      var colspan = jQuery(this).attr("colspan");
      var rowspan = jQuery(this).attr("rowspan");
      if (colspan === undefined) {colspan = 0;}
      if (rowspan === undefined) {rowspan = 0;}
      jQuery(this).attr("rowspan",colspan);
      jQuery(this).attr("colspan",rowspan);           
      var existing_row = jQuery(this).attr("row");
      var existing_col = jQuery(this).attr("col");
      row_count = col + prev_colspan;

      if (existing_row === undefined || existing_col === undefined) {
        jQuery(this).attr("row", row + prev_rowspan);
        jQuery(this).attr("col", col + prev_colspan);
      }
      else {
        row_count = existing_row;
        jQuery(this).attr("col", existing_row);
        jQuery(this).attr("row", existing_col);
      }
      if(newrows[row_count] === undefined) { newrows[row_count] = jQuery("<tr></tr>"); }
      newrows[row_count].append(jQuery(this));
      if (existing_row === undefined || existing_col === undefined) {
        if (colspan > 0) {prev_colspan = parseInt(colspan) - 1; }
        else {prev_colspan = 0;}
        if (rowspan > 0) {prev_rowspan = parseInt(rowspan) - 1;}
        else {prev_rowspan = 0;}
      }
    });
  });
  jthis.find("tr").remove();
  jQuery.each(newrows, function(){
    jthis.append(this);
  });
});

Upvotes: 0

ESS
ESS

Reputation: 175

I hacked away at the function to get it to do what I need. The updated version is below.

function tableTransform(objTable) {
    if (typeof objTable != 'undefined') {
        objTable.each(function () {
            var $this = $(this);
            var newrows = [];
            $this.find("tbody tr, thead tr").each(function () {
                var i = 0;
                $(this).find("td, th").each(function () {
                    i++;
                    if (newrows[i] === undefined) {
                        newrows[i] = $("<tr></tr>");
                    }
                    newrows[i].append($(this));
                });
            });
            $this.find("tr").remove();
            $.each(newrows, function () {
                $this.append(this);
            });
        });
        //switch old th to td
        objTable.find('th').wrapInner('<td />').contents().unwrap();
        //move first tr into thead
        var thead = objTable.find("thead");
        var thRows = objTable.find("tr:first");
        var copy = thRows.clone(true).appendTo("thead");
        thRows.remove();
        //switch td in thead into th
        objTable.find('thead tr td').wrapInner('<th />').contents().unwrap();
        //add tr back into tfoot
        objTable.find('tfoot').append("<tr></tr>");
        //add tds into tfoot
        objTable.find('tbody tr:first td').each(function () {
            objTable.find('tfoot tr').append("<td>&nbsp;</td>");
        });
        return false;
    }
}

I also created the updated fiddle below.

http://jsfiddle.net/4tobvo05/7/

I'm sure there are many optimizations or improvements that could be made so I am open to any suggestions that anyone might have.

Upvotes: 5

Related Questions