JavaScriptJQuery swap horizontal and vertical order of HTML table - Stack Overflow

I have a plex HTML table with horizontal and vertical headings looking like this.The HTML code is simpl

I have a plex HTML table with horizontal and vertical headings looking like this.

The HTML code is simple:

<table>
    <tr>
      <th>(empty)</th>
      <th>Heading 1</th>
      <th>Heading 2</th>
    </tr>
 <tr>
  <th>Heading A</th>
     <td>content for 1 and A</td>
     <td>content for 2 and A</td>
 </tr>
 <tr>
  <th>Heading B</th>
     <td>content for 1 and B</td>
     <td>content for 2 and B</td>
 </tr>
 <tr>
  <th>Heading C</th>
     <td>content for 1 and C</td>
     <td>content for 2 and C</td>
 </tr>
</table>

Now, I want to give the users of my website the possibility to swap the content of the table. I.e.: change the horizontal and vertical order, so that afterwards the vertical headings are horizontal, the horizontal headings are vertical and the table cells accordingly. Sounds plicated, but you will get it by looking at the picture:

The HTML would be now:

<table>
    <tr>
      <th>(empty)</th>
      <th>Heading A</th>
      <th>Heading B</th>
      <th>Heading C</th>
    </tr>
 <tr>
  <th>Heading 1</th>
     <td>content for 1 and A</td>
     <td>content for 1 and B</td>
     <td>content for 1 and C</td>
 </tr>
 <tr>
  <th>Heading 2</th>
     <td>content for 2 and A</td>
     <td>content for 2 and B</td>
     <td>content for 2 and C</td>
 </tr>
</table>

Technically speaking, evey table cell (th and td) has to swap its indices: The column index should bee the row index and the column index should bee the rown index. But how do I do that using JavaScript and or JQuery?

I already found out how to get the row and column index:

//column
$(this).parent().children().index(this);

//row
$(this).parent().parent().children().index(this.parentNode);

But there seems no JQuery function for "set table cell position", there is just .inserAfter and honestly, I don't know how to cope with that.

I have a plex HTML table with horizontal and vertical headings looking like this.

The HTML code is simple:

<table>
    <tr>
      <th>(empty)</th>
      <th>Heading 1</th>
      <th>Heading 2</th>
    </tr>
 <tr>
  <th>Heading A</th>
     <td>content for 1 and A</td>
     <td>content for 2 and A</td>
 </tr>
 <tr>
  <th>Heading B</th>
     <td>content for 1 and B</td>
     <td>content for 2 and B</td>
 </tr>
 <tr>
  <th>Heading C</th>
     <td>content for 1 and C</td>
     <td>content for 2 and C</td>
 </tr>
</table>

Now, I want to give the users of my website the possibility to swap the content of the table. I.e.: change the horizontal and vertical order, so that afterwards the vertical headings are horizontal, the horizontal headings are vertical and the table cells accordingly. Sounds plicated, but you will get it by looking at the picture:

The HTML would be now:

<table>
    <tr>
      <th>(empty)</th>
      <th>Heading A</th>
      <th>Heading B</th>
      <th>Heading C</th>
    </tr>
 <tr>
  <th>Heading 1</th>
     <td>content for 1 and A</td>
     <td>content for 1 and B</td>
     <td>content for 1 and C</td>
 </tr>
 <tr>
  <th>Heading 2</th>
     <td>content for 2 and A</td>
     <td>content for 2 and B</td>
     <td>content for 2 and C</td>
 </tr>
</table>

Technically speaking, evey table cell (th and td) has to swap its indices: The column index should bee the row index and the column index should bee the rown index. But how do I do that using JavaScript and or JQuery?

I already found out how to get the row and column index:

//column
$(this).parent().children().index(this);

//row
$(this).parent().parent().children().index(this.parentNode);

But there seems no JQuery function for "set table cell position", there is just .inserAfter and honestly, I don't know how to cope with that.

Share Improve this question asked Sep 5, 2014 at 8:27 ciscis 1,39118 silver badges61 bronze badges 1
  • the normal word for this operation on an array is "transposing". Searching for that may produce answers. – Alnitak Commented Sep 5, 2014 at 9:10
Add a ment  | 

6 Answers 6

Reset to default 2

Change your html like this

<table>
<tbody>
    <tr>
      <td>(empty)</td>
      <td>Heading 1</td>
      <td>Heading 2</td>
    </tr>
 <tr>
  <td>Heading A</td>
     <td>content for 1 and A</td>
     <td>content for 2 and A</td>
 </tr>
 <tr>
  <td>Heading B</td>
     <td>content for 1 and B</td>
     <td>content for 2 and B</td>
 </tr>
 <tr>
  <td>Heading C</td>
     <td>content for 1 and C</td>
     <td>content for 2 and C</td>
 </tr>
 </tbody>
</table>

And call this function

function Swap(){
    var t= document.getElementsByTagName('tbody')[0],
    r= t.getElementsByTagName('tr'),
    cols= r.length, rows= r[0].getElementsByTagName('td').length,
    cell, next, tem, i= 0, tbod= document.createElement('tbody');

    while(i<rows){
        cell= 0;
        tem= document.createElement('tr');
        while(cell<cols){
            next= r[cell++].getElementsByTagName('td')[0];
            tem.appendChild(next);
        }
        tbod.appendChild(tem);
        ++i;
    }
    t.parentNode.replaceChild(tbod, t);
}

Test it here

function invertTable(table){

  var $table = $(table);

  var invertedTable = [];

  for(var i=0 ; i < $table.find('tr:first th').length ; i++){

    invertedTable.push([]);

  }

  $table.find('th,td').each(function(){
    invertedTable[$(this).index()].push($(this).text());    
  })

  var $newTable = $('<table></table>');

  for(var i=0 ; i < invertedTable.length ; i++){

    var $newTr = $('<tr></tr>');

    for(var j = 0 ; j < invertedTable[i].length ; j++){

        if(j == 0 || i == 0){
            $newTr.append('<th>'+invertedTable[i][j]+'</th>');
        }
        else{
            $newTr.append('<td>'+invertedTable[i][j]+'</td>');
        }

    }

    $newTable.append($newTr);
  }

  $table.after($newTable)
  $table.remove();
} 

http://jsfiddle/xybmoadx/1/

Maybe you should build two tables and hide the inapropriate each time.

html :

<table>
    <tr>
      <th>(empty)</th>
      <th>Heading 1</th>
      <th>Heading 2</th>
    </tr>
 <tr>
  <th>Heading A</th>
     <td>content for 1 and A</td>
     <td>content for 2 and A</td>
 </tr>
 <tr>
  <th>Heading B</th>
     <td>content for 1 and B</td>
     <td>content for 2 and B</td>
 </tr>
 <tr>
  <th>Heading C</th>
     <td>content for 1 and C</td>
     <td>content for 2 and C</td>
 </tr>
</table>

<table style="display:none;">
    <tr>
      <th>(empty)</th>
      <th>Heading A</th>
      <th>Heading B</th>
      <th>Heading C</th>
    </tr>
 <tr>
  <th>Heading 1</th>
     <td>content for 1 and A</td>
     <td>content for 1 and B</td>
     <td>content for 1 and C</td>
 </tr>
 <tr>
  <th>Heading 2</th>
     <td>content for 2 and A</td>
     <td>content for 2 and B</td>
     <td>content for 2 and C</td>
 </tr>
</table>

notice the style: "display:none;" on second table.

Now all you need to do is toogle tables when ever you whant. Lets say you want to toggle on table click :

$('table').on('click', function() {
  $('table').toggle();
});

This solution assums your table is static. It is a quick and easy workarround though. Hope that helps

PS: you can test it here

function transpose(arr){
    return Object.keys(arr[0]).map(function (c) { return arr.map(function (r) { return r[c]; }); });
}
function transposeTable(table){
    var rows = [];
    var tableString = '';
    table.find('tr').each(function(i,row){
        var rowArray = [];
        row = $(row);
        row.find('th,td').each(function(i,cell){
            cell = $(cell);
            rowArray.push({
                value : cell.text(),
                type : cell.is('th') ? 'th':'td'
            })
        })
        rows.push(rowArray);
    });
    rows = transpose(rows);
    rows.forEach(function(row){
        tableString += '<tr>';
        row.forEach(function(cell){
           tableString += '<' + cell.type + '>';
           tableString += cell.value;
           tableString += '</' + cell.type + '>';  
        })
        tableString += '</tr>';
    });
    return tableString;
}

JSfiddle

Not clean but it works .

Buid the array dynamically from javascript. That would be the easiest way to make it... as well as maintain it.

Say a multi-dimensional array [x][y] represents all you need. [0][0] will obviously be null...

Define a table element in HTML give it an ID, say 'table'... In JavaScript then...

Defining it should be easy...

var t = new Array();
t[0] = new Array();
t[0][0] = 'Heading 1';
t[0][1] = 'Heading 2';

and so on..

On jQuery's Document Ready event, you can initialize it...

$(document).ready(function() {
    for (var i = 0; i < t.length; i++) {
        $('#table').append('<tr id=tr' + 0 + '></tr>');
        for (var j = 0; j < t[i].length; j++) {
            if (i == 0)
                $('#tr' + i).append('<th>' + t[i][j] + '</th>');
            else
                $('#tr' + i).append('<td>' + t[i][j] + '</td>');
        }
    }

    var t_trans = t[0].map(function(col, i) {
        return t.map(function(row) {
            return row[i];
        });
    });
});

I've used code from this answer to transpose the created array and store it in a different variable. Transposing a 2D-array in JavaScript

Now all you need to do on click of the 'Transpose Button' in HTML is delete existing markup inside the 'table', and recreate it using the transposed array.. so during the onclick event,

$('#table').empty();
for (var i = 0; i < t_trans.length; i++) {
    $('#table').append('<tr id=tr' + 0 + '></tr>');
    for (var j = 0; j < t_trans[i].length; j++) {
        if (i == 0)
            $('#tr' + i).append('<th>' + t_trans[i][j] + '</th>');
        else
            $('#tr' + i).append('<td>' + t_trans[i][j] + '</td>');
    }
}

This should do it... Hell, you can even make a posite function taking the array as an argument to do the job for you, something like function populate(arr){} and the nested loop inside..

function populate(arr){
    for (var i = 0; i < arr.length; i++) {
        $('#table').append('<tr id=tr' + 0 + '></tr>');
        for (var j = 0; j < arr[i].length; j++) {
            if (i == 0)
                $('#tr' + i).append('<th>' + arr[i][j] + '</th>');
            else
                $('#tr' + i).append('<td>' + arr[i][j] + '</td>');
        }
    }
}

and call populate(t) on ready, populate(t_trans) after emptying it on button-click.

Look at this jsfiddle I created for you:

http://jsfiddle/carloscalla/yuhx2tgk/3/

It stores the table cell's values in arrays and builds up a table from them. Then swaps the order when button is clicked.

HTML:

<div id="table-wrapper"></div>
<button id="toggler">Toggler</button>

JS:

var max_rows = 4;
var a = new Array();
for (i = 0; i < max_rows; i++)
    a[i] = new Array();

a[0][0] = "(empty)";
a[0][1] = "Heading 1";
a[0][2] = "Heading 2";

a[1][0] = "Heading A";
a[1][1] = "content 1 A";
a[1][2] = "content 2 A";

a[2][0] = "Heading B";
a[2][1] = "content 1 B";
a[2][2] = "content 2 B";

a[3][0] = "Heading C";
a[3][1] = "content 1 C";
a[3][2] = "content 2 C";

var direction = 0;
// 0 for horizontal
// 1 for vertical

function changeDirection(){
    if (direction == 1) direction = 0;
    else if (direction == 0) direction = 1;
    resetTable();
}
function resetTable(){
    var $table_body = $('<table><tbody></tbody></table>');

    if (direction == 0){
        for (x = 0; x < a.length; x++){
            $table_body.append('<tr></tr>');
            $last_row = $table_body.find('tr').last();
            for (v = 0; v < a[x].length; v++){
                $last_row.append('<td>' + a[x][v] + '</td>');
            }
        }
    }
    else{
        for (x = 0; x < a[0].length; x++){
            $table_body.append('<tr></tr>');
            $last_row = $table_body.find('tr').last();
            for (v = 0; v < a.length; v++){
                $last_row.append('<td>' + a[v][x] + '</td>');
            }
        }        
    }

    $('#table-wrapper').html($table_body);
}
$('#toggler').on('click', changeDirection);

Results are these:

Original table:

Updated table:

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744723971a4590076.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信