Fitting content horizontally [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am rewriting a web application that visually represents data and would like to make the result fill the available width automatically (the previous version had a few user selectable scaling factors). I have simplified the layout to this:
.bar {
height: 25px;
background: green;
color: white;
}
<table>
<thead>
<tr>
<th></th>
<th>column #1</th>
<th>column #2</th>
</tr>
</thead>
<tbody>
<tr>
<td>row #1</td>
<td>
<div class="bar" style="width:50px">
cell #1
</div>
</td>
<td>
<div class="bar" style="width:150px">
cell #2
</div>
</td>
</tr>
<tr>
<td>row #2</td>
<td>
<div class="bar" style="width:100px">
cell #3
</div>
</td>
<td>
<div class="bar" style="width:75px">
cell #4
</div>
</td>
</tr>
</tbody>
</table>
The width of the bars should be adjusted so that the table as a whole fills the horizontally available space (the left column should keep its width and ideally the height of the table should not be altered). The amount of columns as well as the amount of rows will vary.
I have full control over the generated html, so the solution may use a different markup (just note that the calculated bar widths are not limited to a few values).
It is important that the relative lengths of the bars are not changed. In this example, the bar in cell #4 should always be 50% longer than the one in cell #1. It should be possible to have text inside the bars and it should not be stretched (therefore, I could not solve my problem with CSS transformations).
The solution may use JavaScript. I think that I could make it work using only JavaScript by measuring the left over space and then scaling each bar manually, but this seems fragile and difficult to maintain to me (the given example is simplified).
Is there an elegant solution? I found it quite hard to search for this problem, so I might have overlooked something (usually I never need to ask questions as others have had similar problems before).
Edit: It seems that I wrote too much text and the actual question became unclear. I am looking for a solution that scales the bars inside the table from the given code snippet so that the table takes up all the available vertical horizontal (too hasty edit) space. The caveat is, that the contained bars should keep their relative lengths.

You can accomplish what you want with just a little bit of JavaScript and a slightly modified CSS file. This will calculate the number of columns (minus the initial column) and will distribute their width evenly.
<style>
.bar {
height: 25px;
background: green;
color: white;
}
table{
width: 100%;
}
table tbody tr td:first-child{
width: 20%;
}
table tbody tr td{
width: 40%;
}
</style>
Then your HTML
<table>
<thead>
<tr>
<th></th>
<th>column #1</th>
<th>column #2</th>
</tr>
</thead>
<tbody>
<tr>
<td>row #1</td>
<td>
<div class="bar" data-value="50">
cell #1
</div>
</td>
<td>
<div class="bar" data-value="100">
cell #2
</div>
</td>
</tr>
<tr>
<td>row #2</td>
<td>
<div class="bar" data-value="80">
cell #3
</div>
</td>
<td>
<div class="bar" data-value="75">
cell #4
</div>
</td>
</tr>
</tbody>
</table>
Then some simple JavaScript:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(document).ready(function(){
var v, b, n, max = 0;
var t = $('table');
var w = t.width();
// Set equal width for all columns
var c = (80/(t.find('thead tr th').length-1));
// Set widths of internal bars relative to the max value
$('.bar')
.parent()
.css({width: c + "%"})
.end()
.each(function(){
// Determines max value
v = parseFloat($(this).attr('data-value'));
if(v>max){
max = v;
}
})
.each(function(){
// Sets each bar to be a percent width based on max value
b = $(this);
n = (((parseFloat(b.attr('data-value')) / max) * 100));
b.css({width: n + "%"})
});
});
</script>

Create a class on the first column you require to be "fixed",also 2nd and 3rd columns.Add id'sto the 4 div bars so we can manipulate them with respect to their widths:
HTML
<table>
<thead>
<tr>
<th class="fixed"></th>
<th class="col">column #1</th>
<th class="col">column #2</th>
</tr>
</thead>
<tbody>
<tr>
<td class="fixed">row #1</td>
<td class="col">
<div class="bar" id="cell1" style="width:50px">
cell #1
</div>
</td>
<td class="col">
<div class="bar" id="cell2" style="width:150px">
cell #2
</div>
</td>
</tr>
<tr>
<td class="fixed">row #2</td>
<td class="col">
<div class="bar" id="cell3" style="width:100px">
cell #3
</div>
</td>
<td class="col">
<div class="bar" id="cell4" style="width:75px">
cell #4
</div>
</td>
</tr>
</tbody>
</table>
Next apply 100% width on the table, then apply the desired widths to your three columns respectively so that they sum up to 100%.
CSS
table{
width: 100%;
}
.bar {
height: 25px;
background: green;
color: white;
}
.fixed{
width: 200px;
text-align: center;
}
.col{
text-align: left;
width: auto;
}
Finally,get each div by its id and set its width as follows,taking in account that 150px is your base here:
JS
document.getElementById("cell1").style.width = ((50/150)*100)+"%";
document.getElementById("cell2").style.width = ((150/150)*100)+"%";
document.getElementById("cell3").style.width = ((100/150)*100)+"%";
document.getElementById("cell4").style.width = ((75/150)*100)+"%";
I hope that was helpful!

Related

How to alternate table row colors when your row has inner rows [duplicate]

This question already has an answer here:
nth-child to alternate by 2 rows [duplicate]
(1 answer)
Closed 2 months ago.
I'm trying to add alternate table row colors in my website for NBA live scores but my table is a little weird since each table row contains an inner table row for the given quarter of the game. I'd like for each team1, scores, quarter, and team2 combination to have the same background color. Here's what it currently looks like and my code:
HTML:
<table>
<thead>
<tr>
<th class="left" style="width:40%; ">Home</th>
<th style="width:10%;" colspan="2">Scores</th>
<th class ="right" style="width:40%;">Away</th>
</tr>
</thead>
<tbody id="tableData">
</tbody>
</table>
Javascript:
else {
data += `<tr>
<td class="left" rowspan="2"> ${item.team1} <img src=${item.team1Img}></td>
<td> ${item.score1} </td>
<td> ${item.score2} </td>
<td class="right" rowspan="2"> <img src=${item.team2Img}> ${item.team2}</td>
</tr>
<tr>
<td class="period" colspan="2">Final</td>
</tr>`;
}
CSS:
tr:nth-child(3n+0) {
background-color: #1b1b1b;
color: #fff;
}
Maybe all I need is a different nth child formula, not sure how it works and couldn't find more advanced resources online.
Thanks in advance!
Found an answer after rewording my question a few times: tr:nth-child(4n+1), tr:nth-child(4n+2)
This would select every 2 table rows.
Answer found here: nth-child to alternate by 2 rows

Change CSS class declaration or actually apply style to every element?

I have a table with over 400 rows and about 90 columns. The visibility of the columns should be dynamic. I already assigned a css class .column(x) to every cell, where (x) is the column's index/count. Now i can change visibility in two ways:
$('.column5').css('display','block');
But that has to loop over 400 cells and possibly re-render the html on every iteration (?). The other method is:
$('.style').html().replace('.column5{display:none}','.column5{display:block}');
Where
<style class='style'>
.column1{display:none}
.column2{display:none}
.column3{display:none}
.column4{display:none}
.column5{display:none}
...
</style>
I'm using the first method now, but it's naturally quite slow with so many cells to change. The question is: could there be any performance gain from using the second method? Does it even make sense/is it a bad practice?
Thanks in advance!
I wouldn't do either. Instead, I'd have rules in the CSS like this:
.hide-column5 .column5 {
display: none;
}
...and then toggle the hide-column5 class on the container of the cells (e.g., the table or tbody as appropriate).
Example:
$("input[type=checkbox]").on("click", function() {
var cls = this.getAttribute("data-cls");
$("table").toggleClass(cls, !this.checked);
});
.hide-column1 .column1 {
display: none;
}
.hide-column2 .column2 {
display: none;
}
.hide-column3 .column3 {
display: none;
}
<table>
<thead>
<tr>
<th class="column1">Col 1</th>
<th class="column2">Col 2</th>
<th class="column3">Col 3</th>
</tr>
</thead>
<tbody>
<tr>
<td class="column1">1</td>
<td class="column2">2</td>
<td class="column3">3</td>
</tr>
<tr>
<td class="column1">1</td>
<td class="column2">2</td>
<td class="column3">3</td>
</tr>
<tr>
<td class="column1">1</td>
<td class="column2">2</td>
<td class="column3">3</td>
</tr>
</tbody>
</table>
<div>
<label>
<input checked type="checkbox" data-cls="hide-column1"> Show 1
</label>
</div>
<div>
<label>
<input checked type="checkbox" data-cls="hide-column2"> Show 2
</label>
</div>
<div>
<label>
<input checked type="checkbox" data-cls="hide-column3"> Show 3
</label>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Make tr width match thead width on sticky table header

I have a sticky table header that I am working on. Right now, the user scrolls passed the header, and the header sticks correctly. The problem I am having is that tableHeaderRow is not the same width as tableHeader.
Current steps for sticky header:
Ajax call to fill table with data
Save column widths
Make tableHeader position:absolute
Set column widths back into tableHeader (this is where it gets close but about 100 pixels short)
Tried
Set tableHeaderRow to the expected width.
Set tableHeaderRow to 100% width.
Remove padding and margin
HTML
<table id="table" class="table tablesorter table-responsive table-striped table-hover" style="overflow:auto;border-collapse:collapse;">
<thead id='tableHeader' style="background-color:LightBlue;">
<tr id='tableHeaderRow' >
<th id="col1" class='header'>Column1</th>
<th id="col2" class='header'>Column2</th>
<th id="col3" class='header'>Column3</th>
<th id="col4" class='header'>Column4</th>
<th id="col5" class='header'>Column5</th>
<th id="col6" class='header'>Column6</th>
<th id="col7" class='header'>Column7</th>
</tr>
</thead>
<tbody id='tableBody'>
</tbody>
</table>
Save off widths
col1Width = $('#col1').width();
col2Width = $('#col2').width();
col3Width = $('#col3').width();
col4Width = $('#col4').width();
col5Width = $('#col5').width();
col6Width = $('#col6').width();
col7Width = $('#col7').width();
Stick Scroll Event Listener
var tableHeaderTop = $("#tableHeader").offset().top;
var above = true;
//Window scroll event listener to fix table headers
$( window ).scroll(function() {
if(tableHeaderTop - $(window).scrollTop() <= 0){
if(above){
$('#tableHeader').css({
position:'absolute',
top: $(window).scrollTop() - $("#top").height() -15,
width:$('table#table').width(),
});
$('.column1Value').width(col1Width);
$('#col1').width(col1Width);
$('.column2Value').width(col2Width);
$('#col2').width(col2Width);
$('.column3Value').width(col3Width);
$('#col3').width(col3Width);
$('.column4Value').width(col4Width);
$('#col4').width(col4Width);
$('.column5Value').width(col5Width);
$('#col5').width(col5Width);
$('.column6Value').width(col6Width);
$('#col6').width(col6Width);
$('.column7Value').width(col7Width);
$('#col7').width(col7Width);
above = false;
}else{
$('#tableHeader').css({
top: $(window).scrollTop() - $("#top").height() -15,
});
}
}else{
$('#tableHeader').css({
position:'static',
});
above = true;
}
});
Please ask for any clarification. Working on a bootply to show issue.
Note: I made a bootply for the issue, but it works as I would want it to on bootply. This leads me to believe it would be some sort of 3rd party plugin that changes CSS. I will update with an answer when I have one, in the mean time if anyone wants to use my custom sticky table header code (thanks to others who helped) you're welcome to do so.
Well, this may not completely answer your question.
But, for what you're trying to do - this jQuery plugin is pretty much the best I've seen out there: http://www.fixedheadertable.com/
Doing a google search I also found a pure css solution (that I have no personal experience with, but if it works as intended that's just cool!): http://jsfiddle.net/dPixie/byB9d/3/
I did a script like that myself once too.
A simplified version of it was looking something like this.
jsFiddle: http://jsfiddle.net/L0oy2L01/
HTML (sorry for inline css styling... feel free to add your own classes!)
<div>
<table>
<tr style="background-color: #ccc;">
<td data-col="1" class="header">
Column1
</td>
<td data-col="2" class="header">
Column2
</td>
<td data-col="3" class="header">
Column3
</td>
</tr>
</table>
</div>
<div id="contentDiv" style="max-height: 50px; overflow-y: auto;">
<table class="contentTable">
<tr>
<td data-col="1" class="content">
My Content1
</td>
<td data-col="2" class="content">
My Content2
</td>
<td data-col="3" class="content">
My Content3
</td>
</tr>
<tr>
<td data-col="1" class="content">
My Content4
</td>
<td data-col="2" class="content">
My Content5
</td>
<td data-col="3" class="content">
My Content6
</td>
</tr>
<tr>
<td data-col="1" class="content">
My Content7
</td>
<td data-col="2" class="content">
My Content8
</td>
<td data-col="3" class="content">
My content9
</td>
</tr>
</table>
</div>
jQuery
<script type="text/javascript">
$(document).ready(function(){
var totalWidth = 0;
$('.header').each(function(){
var colwidth = $(this).outerWidth();
var colnumber = $(this).data('col');
$('.content[data-col="'+ colnumber +'"]').each(function(){
if($(this).outerWidth() >= colwidth){
colwidth = $(this).outerWidth();
}
});
$('td[data-col="'+ colnumber +'"]').css('width',colwidth);
totalWidth += colwidth;
});
//if table height is bigger than contentDiv height there will be a scroll.. therefor we adjust contentDiv to it's content + scrolling
if($('.contentTable').outerHeight() > 50){
$('#contentDiv').outerWidth(totalWidth + 30);
}
});
</script>

how do you create a scroll bar menu that scrolls only on the content and not on the header

I have a list of names : first and last. The list is long, so I need to have a scroll bar menu. When I scroll, I should only scroll on the names and not on the column header.
I managed to do so but the problem is that the second column elements are not displayed right under the column name as you can see here http://jsfiddle.net/MmLQL/44/.
<table border=1 width=200px >
<tr>
<th>First Name</th>
<th>looong column name </th>
</tr>
</table>
<div class="div_scroll">
<table border=1 width=200px >
<tr>
<td>John</td>
<td>Smith</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
</tr>
</table>
</div>
And even if I put the header and the content in the same table, and create a div to wrap the table content and add a class to that div to enable scrolling, it doesn't work http://jsfiddle.net/MmLQL/43/
What am I doing wrong?
You probably don't need javascript for this. Just set the widths of the columns to be equal. Here's a quick example:
th, td {
width: 50%;
}
View it on JSFiddle
You need to set the width of the columns to be the same for each table. Maybe create a css class for each column and apply them to the columns in the tables.
Example CSS classes:
.ColumnOne { width: 40%; }
.ColumnTwo { width: 60%; }
Then apply to the columns:
<table border=1 width=200px >
<tr>
<th class="ColumnOne">First Name</th>
<th class="ColumnTwo">looong column name </th>
</tr>
</table>
<div class="div_scroll">
<table border=1 width=200px >
<tr>
<td class="ColumnOne">John</td>
<td class="ColumnTwo">Smith</td>
</tr>
...

HTML column width changes when table row is hidden

I am a relative newcomer to web programming, so probably I am making some obvious mistake here.
When I am trying to hide a row in a table from javascript like rows[i].style.display = 'none', the table layout is getting completely broken. Originally, the cell content was getting wrapped, and the table width was getting shrunk. I then added style="table-layout: fixed" in the table tag and style="white-space:nowrap" in each td. This stopped the line wrapping, but still the content was not aligned on a line. Cells started moving left if there is space and column width varied from one row to another. I then added a fixed width to each of the th and td element and also to the div containing the table. Still the problem remained.
My current HTML is something like the following.
<div style="width: 300px">
<table id="errorTable" width="100%" cellpadding="5" cellspacing="2" style="table-layout: fixed">
<tr id="HeaderRow">
<th style="width: 100px;">Header 1</th>
<th style="width: 50px;">Header 2</th>
<th style="width: 150px;">Header 3</th>
</tr>
<tr id="DetailRow1">
<td style="white-space:nowrap; width: 100px;">Data 1_1 in Row 1</td>
<td style="white-space:nowrap; width: 50px;">Data 1_2 in Row 1</td>
<td style="white-space:nowrap; width: 150px;">Data 1_3 in Row 1</td>
</tr>
<tr id="DetailRow2">
<td style="white-space:nowrap; width: 100px;">Data 2</td>
<td style="white-space:nowrap; width: 50px;">Data 2</td>
<td style="white-space:nowrap; width: 150px;">Data 2</td>
</tr>
<tr id="DetailRow3">
<td style="white-space:nowrap; width: 100px;">Data 3_1</td>
<td style="white-space:nowrap; width: 50px;">Data 3_2</td>
<td style="white-space:nowrap; width: 150px;">Data 3_3</td>
</tr>
</table>
</div>
When the table is displayed first time, the columns are aligned properly, with width 100, 50 and 150 px respectively. But if a row, say the second one is hidden, the cell width of the remaining two displayed rows are no longer fixed at 100, 50 and 150 and data is no longer aligned vertically. Please note that the overall table width remains 300 px. Data in each cell moves left if there is available space and the additional space is used by the last, in this case, third column.
The following post was helpful but did not solve my problem fully, as you can see.
Hiding table rows without resizing overall width
Any help will be most welcome.
The problem is the display type that you use to make the table-row visible.
To hide a table-row use display="none"
To show a table-row use display="table-row"
I did a sample so you can see these in action.
function show(){
document.getElementById('trB').style.display='table-row';
}
function hide(){
document.getElementById('trB').style.display='none';
}
#import url("https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css");
table{
border: 1px solid #ccc;
}
<table id="myTable" class="table table-striped table-hover">
<thead>
<tr>
<td>#</td>
<td>Letter</td>
</tr>
</thead>
<tbody>
<tr id="trA">
<td>1</td>
<td>A</td>
</tr>
<tr id="trB">
<td>2</td>
<td>B</td>
</tr>
<tr id="trC">
<td>3</td>
<td>C</td>
</tr>
</tbody>
</table>
<button id="showB" onclick="show()">show B</button>
<button id="hideB" onclick="hide()">hide B</button>
Hope this could help who are struggling with the same problem.
Instead of using display: none; I used visibility: collapse; for the hidden rows. This still keeps the width of the columns and the whole layout.
I had the same problem: I tried to hide a column by elem.style.display="none" but when showing again the layout was broken. This display-style worked for me:
columns.item(i).style.display = "table-cell";
Always fix the width of your columns. Would that sole your problem?
.myTable td{ width:33% !important; }
Ideally, you should also enclose header and body sections using thead and tbody
<table>
<thead>
<tr> ... </tr>
</thead>
<tbody>
.
.
.
</tbody>
</table>
I'm having the same problem. I threw a span inside of each table to see if I could force the width and it seems to work. It's ugly though.

Categories