I have a huge table containing data in vertical and horizontal directions...
Like this: jsfiddle
I am hoping to make the far left column and the top row fixed in a way that when I am scrolling in both directions, I am able to keep the these two (column and row) in place. But only move the content.
How to achieve this with JS/CSS?
I am guessing a pure css solution won't do it, since there is a two-way scroll.
someclass { position: fixed }
The entire code required to answer your question is too large to include here. Instead, I'll link you to the JSBin which holds the answer, and just include the styling and javascript.
The caveats are:
If you are dead set on using tables instead of divs to display your data, then you're going to have a bad time formatting the answer I gave you, especially if the data in the cells are varying widths and heights.
In order to accomplish this, you must go through each row and column header, then set their respective widths and heights to the max between their widths/heights and the widths/height of the rows in the table. The reason why their widths and heights aren't automatically set respective to the rest of the cells in the table is because upon setting their position: fixed style attribute, you basically break them out of the table.
So, if you have the power, consider using divs instead and breaking the row headers out into a separate div you can position: fixed and emulate the current behavior of the column headers.
Another bonus is that you will have a performance increase because jQuery will not be iterating through every row to adjust the row headers every time you scroll.
You must use jQuery UI.
HTML:
<!-- Notice I removed background and border color from table tag -->
<table border="0" width="100%" cellpadding="3" cellspacing="1">
<tr>
<td>Dead Cell</td><!-- this cell is not shown -->
...
CSS:
/* Make white space above table since we broke the column headers out of the table */
table {
margin-top: 51px;
position: relative;
}
table td {
border: 1px solid #FFCC00;
height: 44px;
background-color: #FFFFCC;
}
/* styling for column headers */
table tr:first-child {
position: fixed;
top: 0;
left: 57px;
z-index: 100;
}
/* remove first cell in top left position */
table tr:first-child td:first-child {
display: none;
}
table tr:first-child td,
table tr {
position: relative;
}
table tr:first-child td {
background: orange;
}
table tr td:first-child {
background: orange;
position: fixed;
width: 39px
}
/* Make white space to the left of table since we broke the row headers out of the table */
table tr:nth-child(n+2) td:nth-child(2) {
margin-left: 48px;
display: block;
}
JS:
$(function(){ // When document is loaded and ready
$(window).scroll(function() { // When we scroll in the window
// Move column headers into place
$('table tr:first-child td').css('left', - $(this).scrollLeft());
// Move row headers into place
$('table tr td:first-child').each(function() {
$(this).position({ // jQuery UI overloaded function
my: "left top",
at: "left top",
of: $(this).parent(),
using: function(pos) {
$(this).css('top', pos.top);
}
});
});
});
});
Again, here is the link to the JSBin.
Related
I have a table in bootstrap with text inside each td. I don't know if this is possible but I want to fill the whitespace with ellipsis.
The reason I do not want a border bottom is that I do not want the text underlined.
Here is my table and what I have tried so far.
The first and last child td are aligned left and right respectively. Any td in the center is center aligned. The idea is to have the ellipsis fill whitespace on the right with left align. Whitespace on the left with right align and on both sides for the center.
My first thought was to use css :before and :after and overfill the content with '.......................' then break with text-overflow: ellipsis like.
.table-menu .table-responsive td:first-child:after, .table-menu .table-responsive td:last-child:before {
text-overflow:ellipsis;
content: '.......................';
}
but as the table is responsive, this will not work. The tables need to be fixed width for the result to work. So overfilling the content just pushed it to a new line.
Is there a way in css or js to achieve this or do I need another approach to filling the whitespace?
Here is a jsfiddle of my above code https://jsfiddle.net/h3n18huh/1/
I have an idea for this, you can add a label or span inside all <td>, that span/label have white background and <td> have background image with a dot repeated. so the span and label will cover the dots with the white background and the ellipsis will work on any resolution and alineation.
Example:
td:nth-child(1) { text-align: left; }
td:nth-child(2) { text-align: center; }
td:nth-child(3) { text-align: right; }
span {
background-color: white;
display: inline-block;
padding: 2px 5px;
}
td {
background: url(http://s9.postimg.org/5hyiu7din/dot.png) left bottom repeat-x;
}
<table width="100%">
<tr>
<td><span>Left</span></td>
<td><span>Center</span></td>
<td><span>Right</span></td>
</tr>
</table>
I have a table here created using JS dynamically, it contains data more than what a screen shows so I need to implement scroll functionality and the main thing is I also need table width to be 100%. Please anyone?
var table = $('#mydemo1');
for (var i = 0; i <= result.length; i++)
{
doc1=result[i];
var tbody = $("<tbody>").appendTo(table);
var tr = $("<tr>").appendTo(tbody);
var td = $("<td>").html(doc1.Name).data(doc1).appendTo(tr);
}
.mytdemo1 td{font-family:Arial, sans-serif;font-size:14px;padding:10px 7px;border-style:solid;border-width:0px;overflow:hidden;word-break:normal;border-color:red;color:#444;background-color:#F7FDFA;}
.mytdemo1 td:hover {
cursor:pointer;
color: #ccc;
}
.mytdemo1 th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 7px;border-style:solid;border-width:0px;overflow:hidden;word-break:normal;border-color:red;color:#fff;background-color:#26ADE4;}
.mytdemo1 .mytdemo1-yw4l{vertical-align:top}
<div class="empl" id="table-scroll">
<table class="mytdemo1" id="mydemo1" style="display:none;">
<thead>
<tr><th>Employee Name</th></tr>
</thead>
</table>
</div>
You should try to set in the parent element of the table (probably a div) the following style:
/* style to table's parent */
overflow: auto;
width: 100%;
max-height: /* your desired height */
And this style in the table:
width: inherit;
If I got you right, you want to scroll without the scroll bar taking fixed place on the side.
Use:
.vertically_scrollable{
overflow-x:hidden;
overflow-y:auto;
}
as it will only show the vertical scroll bar on top when necessary.
I have a responsive table whose first column I wish to freeze. I took reference from Stack Overflow and tried the code on my table.
CSS code:
.table-responsive>.fixed-column {
position: absolute;
display: inline-block;
width: auto;
border-right: 1px solid #ddd;
}
jQuery code:
$(function(){
var $table = $('.table');
//Make a clone of our table
var $fixedColumn = $table.clone().insertBefore($table).addClass('fixed-column');
//Remove everything except for first column
$fixedColumn.find('th:not(:first-child),td:not(:first-child)').remove();
//Match the height of the rows to that of the original table's
$fixedColumn.find('tr').each(function (i, elem) {
$(this).height($table.find('tr:eq(' + i + ')').height());
});
});
However this code is not working, can anyone tell how to make this thing work, complete code at JSFIDDLE
I want to add bullet points between my flexbox navigation menu, but only have them appear between flex items on the same line. Not at the beginning or end of line, and not at all if the flex item is on the line by itself.
I've been using this (CSS styling for horizontal list with bullet only between elements) question as a starting point, but modified combined the top two answers to make it work with a flexbox.
Here's what I've got:
http://codepen.io/anon/pen/EjQzWZ
JS:
<script>
$(function() {
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top) {
$(lastElement).after( $('<li>').attr('class', 'bullet') );
}
lastElement = $(this);
});
});
</script>
CSS (essentially the exact same as the original question I linked to):
<style>
.bullet {
width: 6px;
height: 7px;
background-position: 50% 50%;
background-repeat: no-repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAOElEQVQI113M0Q3AIBRC0aM76P7jmHSmSj/6mibyc4EQkEEWuYtDmU1SXO1d6H7tjgupIl8+P+cD22cff9U1wbsAAAAASUVORK5CYII=);
}
</style>
Most of the time everything renders correctly. But at certain browser widths, bullet points are added where they shouldn't be. For instance, if the window is re-sized to a width of 678 px (according to the codepen.io counter that displays in the middle of screen while re-sizing), a bullet point appears on the right side of the top row when it shouldn't. (Depending on the browser it may work correctly at 678px, but there are several spots that it does occur, and I've only tested this on Chrome and IE11).
Sometimes a refresh is required to fix the bullet points locations, which is understandable, but at some widths refreshing doesn't help and they reappear incorrectly.
I believe the problem is caused by the extra space the bullet points add.
I think it would be a simpler and cleaner solution to do it entirely via CSS instead of JS, but I'm not sure that's possible with flexbox items. Even though the flexbox items appear to take up a wider width than their content, the css selector ::after seems to only calculate the actual content width.
What is going on with my JS? Can I make it better/cleaner?
You can put your bullet logic in a function, then call that function on page load and attach it to the window resize event.
The updated javascript would look like this:
$(function() {
addBullets();
$(window).resize(addBullets);
});
function addBullets(){
$('li.bullet').remove(); //remove bullets before you add new ones
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top) {
$(lastElement).after( $('<li>').attr('class', 'bullet') );
}
lastElement = $(this);
});
}
See this updated CodePen for a demo.
Also, I don't think this would be possible with pure CSS.
UPDATE
The reason the bullet was showing up on the edge in those certain widths is because the bullets them selves where <li>'s also and were taking up 6px a piece. So when you iterate through the <li>'s It would correctly identify the correct element to put the bullet after, but when the browser renders all the small bullets it would... at certain widths... shove the last <li> to the next line.
To correct this I have created a CSS class for the bullets and will add that to the items that need bullets instead of creating new <li>'s which would take up additional space.
New CSS:
.flex-item {
position:relative; /*added*/
flex: 1 1 auto;
color: #a6a7a9;
font-size:1.5em;
padding: 50px; /*use padding instead of margin for easier absolute positioning of bullet*/
color: black;
text-align: center;
}
.flex-item.bullet:after{
position:absolute;
right:0;
top:50%;
transform:translateY(-50%);
color:blue;
content:"•"; /*could also be "url(data:image/png;base64 ..."*/
}
New Javascript:
function addBullets(){
$('li.bullet').removeClass('bullet'); //remove all bullet classes
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top)
$(lastElement).addClass('bullet'); //add class
lastElement = $(this);
});
}
See this updated CodePen.
If for whatever reason you can't use this CSS class approach you could add your bullets (as <img> or <div>) inside the <li> and position them absolutely with CSS. As long as they don't contribute to the overall width of the <ul> it should work fine.
You can do this using CSS only.
Delete your .bullet definition, and add this CSS:
.flex-container {
margin-left: -10px; //hide the first bullet on each row
}
.flex-item {
position: relative; //so we can have absolute positioning on the :before
}
.flex-item:before {
content: "•"; //the bullet
position: absolute; //positioned absolutely
left: -55px; //account for the 50px margin and the bullet's width
}
Updated CodePen
div:before{
content:"\b7\a0"; /* \b7 is a middot, \a0 is a space */
font-size:30px;
}
Or try this
div:before{
content:"•";
}
You can use the :not(:first-child) selector to apply the bullet to all but the first child.
.flex-row
{
display: flex;
flex-direction: row;
&.bulleted
{
div:not(:first-child):before{
content: "•";
}
}
}
i have a div with with property
<div id="_body_container" style="height: 500px; overflow-x: auto; overflow-y: auto; ">
</div>`
inside this div i have the table which has class views-table, this table has 100% width which makes it's parent div:_body_container scrollable.I want to fix the first and the second column of this table sticky at their positions while the left and right scroll event happen for _body_container
structure is like:
Assuming each section is a <td> element...
CSS
table {
position: relative;
padding-left: (width-of-your-td-elements);
}
table td:first-of-type {
position: absolute;
left: 0;
}
Try that out. It's late and I'm drunk, so I'm not entirely sure on this. Oh, and keep in mind this is using CSS3, which isn't supported in <= IE8.
If this works, you could just add position:absolute; left:0; to a class and target the first element that way.
#vonkly is almost right about position:absolute. But you don't have to set left:0. With left:auto, you can spare position:relative too.
table {
padding-left: (width-of-your-td-elements);
}
table td:first-of-type {
position: absolute;
}