I have HTML table and the table contains 100 Rows and 2 columns (200 cells). I would like the cells to be rearranged randomly with respect to it's original row AND/OR it's original column.
This is how I would represent 4 pieces of data.
<table>
<tr>
<td> Data1 </td>
<td> Data2 </td>
</tr>
<tr>
<td> Data 3 </td>
<td> Data 4 </td>
</tr>
</table>
I'm using HTML and CSS only. I intend on enter the contents of each cell manually Initially.
The Data's represent Images for a gallery which I'm working on. Kindly suggest another opinion if I shouldn't be using tables for such an arrangement.
There's no need to be using a table for this kind of goal. However, to do anything randomly without you sitting at your computer rolling a dice and typing in the result, you will need to use some JavaScript. At the bottom of your page, put something like this:
<script>
var images = document.getElementsByTagName('img');
var randomArrangement = [];
for (var i=0; i < images.length; i++)
{
if (Math.random() > 0.5) {
randomArrangement.push(images.src);
} else {
randomArrangement.unshift(images.src);
}
}
for (var j=0; j < images.length; j++)
{
images[i].src = randomArrangement[i];
}
</script>
That will give you an array of your image URLs in a random order, and fill each one into the existing images. However, this will be much more effective and efficient if done server-side before the page load.
Related
I have a table nested inside another table. The thead of the outside table has 10 columns. The first td of every tr inside the tbody is a normal cell.
The cells 2 through 10 can actually have several sub-rows that are dynamically created. I need these 9 (1 through 9) to line up with the parent table's columns 2 through 10. I'm not sure how to achieve this without changing my overall structure to be a single table with a dynamic rowspan on the first column.
This is overtly complicated to visualize, so here's a JSFiddle to help. That sub-table should span all the way to column '10' of the parent table.
http://jsfiddle.net/23p34/1/
Before I go and switch up my entire architecture so far, I wanted to at least ask if my approach could feasibly work. Perhaps overall, it'd be easier if I did just switch.
You could do something like this: http://jsfiddle.net/23p34/4/
var subTables = $("table").find("table");
var headerColumns = $("table:first").find("tr:first").find("th:not(:first)");
var widths = new Array();
for (i = 0; i < 9; i++){
widths.push($(headerColumns.get(i)).width());
}
$.each(subTables.find("tr"), function(){
var row = this;
var rowCells = $(row).find("td");
for (x = 0; x < 9; x++){
var td = rowCells.get(x);
if ($(td).width() > widths[x]){
widths[x] = $(td).width();
}
}
});
$.each(headerColumns, function(index){
$(this).width(widths[index] + "px");
});
$.each(subTables.find("tr"), function(){
var row = this;
var rowCells = $(row).find("td");
$.each(rowCells, function(index){
$(this).width(widths[index] + "px");
});
});
Make sure to add colspans to the outer table's cells.
<body>
<div>
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
<th>8</th>
<th>9</th>
<th>10</th>
</tr>
</thead>
<tbody>
<tr>
<td>test</td>
<td colspan="9">
Basically you loop through all cells and determine the largest width for that column. Then you go back and set all cells in that column to match the largest width. Its not going to be perfect, so you would need to tweak it a bit. It also isn't the prettiest option. I think you would probably be better served with moving it to one table.
Is it possible to create an HTML/CSS Table that is formatted like the POSIX ls? That is, entries are displayed alphabetically in columns, where the number of columns is dependent on the width of each column?
For example, see in this screenshot how the columns are only as wide as necessary. The fourth column is much wider than than the others, and the third column is narrowest of all as all its file names are short. There are four columns in this screenshot but there could be more if the terminal were wider and fewer if it were narrower.
The number of columns varies based on the width of the terminal and the exact file names in the listing. As more file names are shown, more columns are added. Once the right side of the terminal is reached, ls makes the columns taller. If there are lots of short file names there could be a lot of columns, whereas if the file names are long there would be fewer.
Well, the good-news is that browsers "sorta" support this with table elements and table-layout:auto rendering (this should be the default, and is after an appropriate CSS reset). The bad news is it's only "sorta".
For starters, you must pick the number of columns and render the HTML table such that the items are in the correct column - this includes all sorting! Then, if you don't over-constrain the width of any column in the table, make sure the table is table-layout:auto, and set the width of the table then the results should be similar to that of ls - that is, the columns will "automatically adjust width" based on the content.
To get an "identical" result to ls would require something more heavy-handed, such as using a fixed-font (like that used in a terminal) and manually calculating the column widths (like ls does), perhaps in a <pre> element. CSS/HTML has limitations that ls simply avoids by doing layout calculations itself against a fixed-width terminal.
This is a table as any other. Unless there is something else you didn't specify. You may do something like this
<table>
<colgroup style="width:22%"></colgroup>
<colgroup style="width:25%"></colgroup>
<colgroup style="width:25%"></colgroup>
<colgroup style="width:25%"></colgroup>
<colgroup style="width:3%"></colgroup>
<thead>
<tr>
<th>Closed Day</th>
<th><span>|</span>Is this a paid day?</th>
<th><span>|</span>Last updated date</th>
<th><span>|</span>Last updated by</th>
<th><span>|</span>Current?</th>
</tr>
</thead>
<tbody>
<tr>
<td>08/10/2013</td>
<td>No</td>
<td>02/12/2014</td>
<td>c-jsmith</td>
<td>Yes</td>
</tr>
<tr>
<td>09/01/2013</td>
<td>Yes</td>
<td>02/12/2014</td>
<td>c-kkearney</td>
<td>Yes</td>
</tr>
<tr>
<td>12/25/2013</td>
<td>Yes</td>
<td>01/12/2014</td>
<td>c-jjohnson</td>
<td>Yes</td>
</tr>
<tr>
<td>12/26/2013</td>
<td>Yes</td>
<td>02/01/2014</td>
<td>c-gthompson</td>
<td>Yes</td>
</tr>
</tbody>
Using a table similar to above and the script below with some modifications you should be able to limit the amount of rows and stack to the right with positioning.
<script>
function tableWrap() {
var maxRows = 10;
var table = document.getElementById('myTable');
var wrapper = table.parentNode;
var tableRows = table.rows.length;
var height = 0;
if (tableRows > maxRows) {
for (var i = 0; i < maxRows; i++) {
height += table.rows[i].Height;
}
wrapper.style.height = height + "px";
}
}
</script>
I managed to get something started with javascript:
var outer = document.getElementById("outer");
function setColumns(n) {
var style = outer.style;
style.columnCount = n;
style.MozColumnCount = n;
style.WebkitColumnCount = n;
}
var i = 1;
while (outer.scrollWidth <= outer.offsetWidth) {
setColumns(++i);
}
setColumns(i - 1);
http://jsfiddle.net/jEq4R/2/
It doesn't handle the width, yet, but it at least gives a good number of columns.
EDIT: works in firefox but not webkit
Adjust the width in this jsfiddle and see http://jsfiddle.net/sajith/DdqfA/
HTML
<div>column</div><div>column</div><div>column</div>
<div>column</div><div>column</div><div>column</div>
<div>column</div><div>column</div><div>column</div>
<div>column</div><div>column</div><div>column</div>
<div>column</div><div>column</div><div>column</div>
<div>column</div><div>column</div><div>column</div>
CSS
div {
width: 200px;
display: inline-block;
}
I have an asp.net-mvc website. In my viewmodel I have a collection of cars that I want to display on an HTML table.
I want to show 5 cars per row, so I started something like this:
<table>
#foreach (var car in Model.Cars) {
if (counter == 0) {
<tr>
}
<td>#car.Name</td>
counter++;
if (counter == 5) {
</tr>
}
}
</table>
The issues are I feel like the code above is a little hacky and also what if I have 7 cars, should I put 3 blank <td>s in the last row or cut it off (again even more hacky code)?
I wanted to see if there was a cleaner way in an asp.net-mvc to display a collection in a table with a specific number of entries in the table on a row.
If you want to stick to tables, this looks the least hacky to me
#{
var colSize = 5;
var rows = (int)(Model.Cars.Count() / colSize);
}
<table>
#for (var row = 0; row <= rows ; row++){
<tr>
#foreach(var car in Model.Cars.Skip(row * colSize).Take(colSize))
{
<td>#car.Name</td>
}
</tr>
}
</table>
if you want to fill out the last row with <td> elements, you can put this in front of the <tr>:
#if (row == rows)
{
for(var i=0;i<colSize -( Model.Cars.Count() % colSize); i++){
<td></td>
}
}
You could make this slightly cleaner with something along these lines:
<table>
<tr>
#foreach (var car in Model.Cars) {
<td>#car.Name</td>
<!-- If we've output a fifth cell, break to a new row -->
if (++counter % 5 == 4)
{
</tr><tr>
}
}
</tr>
</table>
However it would probably be better to instead output block-level elements with a fixed width and float them left, like this (excuse the inline styles ;-)):
<div style="width: 300px;">
#foreach (var car in Model.Cars) {
<div style="float: left; width: 55px;">#car.Name</div>
}
</div>
Is there a way I could limit the tds to 4 or any number in the following set up ..please see code below. Right now, its displaying all model items in one single row (as it should according to the code). If the items are a dozen, they are all displayed one single row.. I would like a way to display this four in each row instead of all in one row... (am I talking about table inside a table?) can this be done?
<table>
<tr>
#foreach (var item in Model)
{
<td>
#Html.DisplayFor(modelItem => item.fld1)
#Html.DisplayFor(modelItem => item.fld2)
</td>
}
</tr>
</table>
You could group them:
#{
var chunkSize = 4;
var groupedResult =
from i in Model.Select((value, index) => new { Value = value, Index = index })
group i.Value by i.Index / chunkSize into g
select g;
}
<table>
#foreach (var result in groupedResult)
{
<tr>
#foreach (var item in result)
{
<td>
#Html.DisplayFor(modelItem => item.fld1)
#Html.DisplayFor(modelItem => item.fld2)
</td>
}
</tr>
}
</table>
Obviously the fact that you need to do this means that your view model is not adapted to this view. So adapt it and perform this grouping inside your controller action. Then your view will become simple and readable and not resemble some spaghetti code.
I have a number of tables with the same columns and it would look a lot nicer if they shared the same column widths. Is such a thing possible? Putting them in the same table with some rows with no borders between them isn't an option.
Edit: Yeah I'm aware I can fix the widths myself but I was hoping for something that would tie in to the browser's column width algorithm but simply tied two or more tables together for the purpose of doing that layout.
I didn't think such a thing was possible but I thought I'd check just in case.
If you're not too picky about which column widths the browser comes up with, as long as they're the same across different tables, you can use the CSS table-layout property (supported by all major browsers) in combination with a table width:
table {
table-layout: fixed;
width: 100%;
}
This causes all columns (without a specified width) to have the same width, regardless of the table content.
It's only possible if you can fix-width the columns. If you can set a fixed width then some css like this should work:
td {
width: 25%;
}
You can customize each columns width like this:
<table>
<tr>
<td class="col1">...</td>
<td class="col2">...</td>
</tr>
</table>
...
<table>
<tr>
<td class="col1">...</td>
<td class="col2">...</td>
</tr>
</table>
and then specify the widths like this:
.col1 {
width: 25%;
}
.col2 {
width: 75%;
}
Here's a small JavaScript I made to resize cells to make them equal width in all tables on a page.
function resizeTables()
{
var tableArr = document.getElementsByTagName('table');
var cellWidths = new Array();
// get widest
for(i = 0; i < tableArr.length; i++)
{
for(j = 0; j < tableArr[i].rows[0].cells.length; j++)
{
var cell = tableArr[i].rows[0].cells[j];
if(!cellWidths[j] || cellWidths[j] < cell.clientWidth)
cellWidths[j] = cell.clientWidth;
}
}
// set all columns to the widest width found
for(i = 0; i < tableArr.length; i++)
{
for(j = 0; j < tableArr[i].rows[0].cells.length; j++)
{
tableArr[i].rows[0].cells[j].style.width = cellWidths[j]+'px';
}
}
}
window.onload = resizeTables;
To expand on Ken's answer, you can also specify the exact widths in pixels:
td { width: 250px }
or ems (width of the letter m):
td { width: 32em }
or ex or pt or whatever (well...actually %, pt, px, em, ex might be it). If you need your columns to be different widths, then the easy way is to give the table cells classes:
<table><tr>
<td class="col1">...</td><td class="col2">...</td>...
</tr></table>
and assign column widths to the classes:
td.col1 { width: 48em }
td.col2 { width: 200px }
...
It should be sufficient to assign column widths to the first row in each table. [edit: looks like I've been scooped on that while I was writing]
You could probably also go crazy with the CSS 2 sibling selector, and write something like
tr > td:first-child { width:48em } /* first column */
tr > td:first-child + td { width: 200px } /* second column */
tr > td:first-child + td + td { width: 5% } /* third column */
...
but if you have more than a few columns, that could get ugly. And if you're using some sort of template system or script to generate these tables, I'm sure it'll be easier/clearer to just put the class="col#" attribute on each cell in your template once.
I'm almost shocked that no one has suggested column groups! With it you can give a column a specific class, width, and other helpful properties. And since it's HTML 4.01 it's supported by all browsers that support the doctype.
Luis Siquot answer is the one I used. However instead of using clientWidth, you should use jquery width() function to normalize widths between browsers, and to not calculate padding. Using clientWidth would result in the table cells expanding on ajaxpostbacks because of the padding (if padding used in the TD's).
So, correct code using Luis Siquot's answer would be to replace
var cell = $(this)[0].rows[0].cells[j];
if(!cellWidths[j] || cellWidths[j] < cell.clientWidth) cellWidths[j] = cell.clientWidth;
with
var cell = $($(this)[0].rows[0].cells[j]);
if (!cellWidths[j] || cellWidths[j] < cell.width()) cellWidths[j] = cell.width();
The easiest way is kind of a 'dirty' way, but it works the best.
It does exactly what's required:
Just merge your two tables into one table.
In my case the only thing between the two tables was an h3
So my table
<table>
<tr></tr>
<table>
<h3>Title<h3>
<table>
<tr></tr>
<table>
became this:
<table>
<tr></tr>
<tr><td colspan="6">
<h3>Title<h3>
</td></tr>
<tr></tr>
<table>
this way your table will 'sync' it's size up.
of course this only works when there isn't too much complex stuff in between the two tables, but I'm guessing in most cases it isn't. if it was, the sync wouldn't be needed in the first place.
each pair of tables resize its columns to the same width
similar to Ole J. Helgesen but with jquery and a parameter in order to select which tables equalize.
(I cant vote but it's essentially your solution)
<table data-ss="1" border="1">
<tr><td>asdf<td>129292<td>text
</table>
<table data-ss="1" border=1>
<tr><td>a<td>1<td>each column here has the same size than the table above
</table>
<table data-ss="2" border=1>
<tr><td>asdf<td>129292<td>text
</table>
<table data-ss="2" border=1>
<tr><td>each column here has the same size than the table above<td>a<td>1
</table>
and use this sctipt
$(function(){
resizeTables('1');
resizeTables('2');
});
//please set table html attribute `data-ss="something"` to properly call this js
// ss is short for SharedSize
function resizeTables(sharedSize){
var tableArr = $('table[data-ss='+sharedSize+']');
var cellWidths = new Array();
$(tableArr).each(function() {
for(j = 0; j < $(this)[0].rows[0].cells.length; j++){
var cell = $(this)[0].rows[0].cells[j];
if(!cellWidths[j] || cellWidths[j] < cell.clientWidth) cellWidths[j] = cell.clientWidth;
}
});
$(tableArr).each(function() {
for(j = 0; j < $(this)[0].rows[0].cells.length; j++){
$(this)[0].rows[0].cells[j].style.width = cellWidths[j]+'px';
}
});
}
You can sync the column widths by combining the tables (as suggested by #Stefanvds), but using a tbody + th for each:
table {
border-collapse: collapse;
}
table thead,
table tbody {
border-bottom: solid;
}
table tbody th {
text-align: left;
}
<table>
<thead>
<tr> <th> ID <th> Measurement <th> Average <th> Maximum
<tbody>
<tr> <td> <th scope=rowgroup> Cats <td> <td>
<tr> <td> 93 <th scope=row> Legs <td> 3.5 <td> 4
<tr> <td> 10 <th scope=row> Tails <td> 1 <td> 1
<tbody>
<tr> <td> <th scope=rowgroup> English speakers <td> <td>
<tr> <td> 32 <th scope=row> Legs <td> 2.67 <td> 4
<tr> <td> 35 <th scope=row> Tails <td> 0.33 <td> 1
</table>
Source: Example in the HTML spec itself