Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a html table with dynamically expanding number of columns to fit screen size

I have long list of data (for an example say States and their Abbreviations) I want to display in HTML table. Instead of displaying the data in 2 x 50 table I would like it more compact for larger screens (so the user does not have scroll up and down as much but still won't have to scroll horizontally)

So this would grow dynamically:

State       | Ab
-------------------
Alabama     | AL
Alaska      | AK
Arizona     | AZ
Arkansas    | AR
California  | CA
Colorado    | CO
Connecticut | CT

to:

State       | Ab | State       | Ab |
--------------------------------------
Alabama     | AL | California  | CA |
Alaska      | AK | Colorado    | CO |
Arizona     | AZ | Connecticut | CT |
Arkansas    | AR |

or this:

State       | Ab | State      | Ab | State       | Ab |
---------------------------------------------------------
Alabama     | AL | Arkansas   | AR | Colorado    | CO |
Alaska      | AK | California | CA | Connecticut | CT |
Arizona     | AZ |

etc....

Depending on the screen width.

I am doing this in Rail 3 app with jQuery so I prefer jQuery solution but open to any ideas.

like image 273
Nathan Avatar asked Jun 28 '12 05:06

Nathan


2 Answers

Here's a demo of a tableless solution. It is only currently set to arrange columns on page load and would take some minor additions for resize handling.

DEMO: http://jsfiddle.net/DPRsj/

It's based on a json array I had with array looking like:

   [{"state":"AK","name":"Alaska"}........]

The html could be sent to page without needing to parse json, minor difference in getting length of state list would be needed

HTML:

<div id="state_wrap">
    <div id="state_header"></div>
    <div id="state_list"></div>   
</div>

CSS:( very basic)

.state{  width:150px;  border:1px solid grey; border-top:none}
.st_name{ width: 120px;float:left}
.st_ab{ width:30px; margin-left: 120px;}
#state_header .state{
    font-weight:bold;
    color:blue;
    margin-right:10px;
    width: 150px;
    float:left;
}
.column{ width: 152px; float:left;margin-right:10px;}

JS:

$(function() {
    /* parse json to html*/
    var html = [];    
    $.each(states, function() {
        html.push(stateContainer(this.name, this.state));
    });    
    html.push('<div style="clear:both"></div>');    
    $('#state_list').html(html.join(''))
     /* END parse json to html*/

    var listW = 160, /* column width, including margin, set by css*/
        contW = $('#state_wrap').width();
    var num_cols = Math.floor(contW / listW)
    /* create headings*/
    var topHtml = [];
    for (i = 0; i < num_cols; i++) {
        topHtml.push(stateContainer('State', 'Abr'))
    }

    $('#state_header').html(topHtml.join(''));
    /*END create headings, START: create columns*/
    var start = 0,
        end = 0;
    var state_per_col = Math.floor(states.length / num_cols);
    var $states = $('#state_list .state')
    for (i = 0; i < num_cols; i++) {
        start = end;
        end = start + state_per_col + 1;
        $states.slice(start, end).wrapAll('<div class="column"></div>')
    }
});

function stateContainer(name, abr) {
    return '<div class="state"><div class="st_name">' + name + '</div><div class="st_ab">' + abr + '</div></div>';
}
like image 134
charlietfl Avatar answered Nov 14 '22 22:11

charlietfl


Couldn't find an off-the-shelf solution, but this function should do the trick!

/*
This function will create a table with fixed `COL_WIDTH' (default=150 px) 
that uses as many columns as can be fit into the HTML element with id `table_id'.

A one-dimensional array of values to fill the table with should be passed in as 
`data'.
*/
function fillScreenWithData(table_id, data, COL_WIDTH){
    if (!COL_WIDTH) COL_WIDTH = 150;

    TABLE = $(table_id);
    alert(TABLE);
    TABLE_STRING = "<table>"
    var doc_width = TABLE.width();
    var num_cols = Math.floor(doc_width / COL_WIDTH);
    var num_rows = Math.ceil(data.length / num_cols); 

    for (var i = 0; i < num_rows; i++){
        TABLE_STRING += "<tr>";
        for (var j = 0; j < num_cols; j++){
            TABLE_STRING += "<td>";
            index = i + j*num_rows;
            if (index < data.length) {
                TABLE_STRING += data[index];
            }
            TABLE_STRING += "</td>"
        }
        TABLE_STRING += "</tr>"
    }
    TABLE_STRING += "</table>"
    TABLE.html(TABLE_STRING);
}

// probably fetch this JSON array of data with an AJAX request
var data = ["Alabama", 
        "Alaska",
        "Arkansas",
        "California",
        "Colorado",
        "Connecticut",
        "Extra Item",
        ]

// run the function on page load
$(function(){fillScreenWithData("#table", data)});
like image 27
Alex Avatar answered Nov 14 '22 23:11

Alex