I'm attempting to create a table with reorderable columns using jQuery UI's "sortable" interaction. However, I'm having trouble on IE with table-layout: fixed.
The sortable is attached to the table's thead > tr and works just fine. The table looks correct when not dragging a column heading. While dragging, however, IE increases the width of the table to 100% and makes the dragged heading's column wider to make up the difference. I've tried specifying the width via <col> elements (which seem to be completely ignored by IE?), setting widths on each <td>, using forcePlaceholderSize, and combinations of the three, but nothing seems to work.
Code is below and on jsFiddle. Note that the logic to actually swap columns and correct their widths after dragging is finished hasn't been included; right now, I'm only concerned with the (mis-)behavior while dragging.
HTML:
<table>
<col style="width:90px">
<col style="width:130px">
<col style="width:70px">
<thead>
<tr>
<th style="width:90px">width 90</th>
<th style="width:130px">width 130</th>
<th style="width:70px">width 70</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width:90px">foo</td>
<td style="width:130px">bar</td>
<td style="width:70px">baz</td>
</tr>
<tr>
<td style="width:90px">wibble</td>
<td style="width:130px">wobble</td>
<td style="width:70px">wubble</td>
</tr>
<tr>
<td style="width:90px">lorem</td>
<td style="width:130px">ipsum</td>
<td style="width:70px">dolor</td>
</tr>
</tbody>
</table>
CSS:
table {
border-collapse: collapse;
table-layout: fixed;
}
td, th {
background: white;
border: 1px solid #999;
padding: 0 .25em;
}
JS:
$("thead tr").sortable({
forcePlaceholderSize: true,
helper: "clone",
tolerance: "pointer"
});
Related
I have this short piece of code that allows for sections of a table to be collapsed (they are like collapsible headers). This is neat, but I'm trying to make for the inverse to happen upon loading the page -- to be collapsed by default on load, but expandable when clicked. How would I go about doing this?
My present code, shown below, also features sections that only collapse when the words in the section are clicked, not when the section itself (outside of the words) are clicked. This is because I used labels to make the collapsible. Is there a way to make the entire row expandable/collapsible?
table {
width: 100%;
}
table,
tr,
th,
td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial;
}
[data-toggle="toggle"] {
display: none;
}
<table>
<thead>
<tr>
<th>Name</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tbody class="labels">
<tr>
<td colspan="2">
<label for="section">Click me!</label>
<input type="checkbox" id="section" data-toggle="toggle">
</td>
</tr>
</tbody>
<tbody class="hide">
<tr>
<td>Jack</td>
<td>100</td>
</tr>
<tr>
<td>Jill</td>
<td>300</td>
</tr>
</tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('[data-toggle="toggle"]').change(function() {
$(this).parents().next('.hide').toggle();
});
});
</script>
I'm trying to make for the inverse to happen upon loading the page --
to be collapsed by default on load, but expandable when clicked. How
would I go about doing this?
Simply add a line in your jquery above your toggle function and call on your .hide class selector and use .hide(); Then when you click it the toggle function fires.
also features sections that only collapse when the words in the
section are clicked, not when the section itself (outside of the
words) are clicked. This is because I used labels to make the
collapsible. Is there a way to make the entire row
expandable/collapsible?
Yes... Make your label display as block in your CSS file...
label {
display: block;
}
$(document).ready(function() {
$('.hide').hide();
$('[data-toggle="toggle"]').change(function() {
$(this).parents().next('.hide').toggle();
});
});
table {
width: 100%;
}
table,
tr,
th,
td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial;
}
[data-toggle="toggle"] {
display: none;
}
label {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Name</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tbody class="labels">
<tr>
<td colspan="2">
<label for="section">Click me!</label>
<input type="checkbox" id="section" data-toggle="toggle">
</td>
</tr>
</tbody>
<tbody class="hide">
<tr>
<td>Jack</td>
<td>100</td>
</tr>
<tr>
<td>Jill</td>
<td>300</td>
</tr>
</tbody>
</table>
Several things going on here...
You were hiding your checkbox, which I don't think was your intent.
Check this example, where I fixed some things: https://jsfiddle.net/za73qf65/
Fixes include:
changing the name of your "hide" class to "hidable"
defaulting that "hidable" class to be display:none
unhiding your checkbox
changing your change() event handler to a click() (optional)
attaching your event handler to a button with an ID (you can vary that)
Point is, with my changes, your example works. You might want to tweak it for a more specific need.
I'd like to create a table with content from my database. I have a table without a header for multiple reasons (e.q. scrolling). Is it possible set the colums to the same width as the table before without JS? I dont want to add a class to each td element if possible. Not all columns have the same width. Nth-child is a bad solution because I have multiple tables.. :/
Here is a shorter version of my table:
table, th, td {
border: 1px solid #000;
}
table {
border-collapse: collapse;
}
.h1 {
width: 125px;
}
.h2 {
width: 150px;
}
<table>
<tr>
<th class="h1">
<span>a</span>
</th>
<th class="h2">
<span>b</span>
</th>
</tr>
</table>
<table>
<tr>
<td>
<span>c</span>
</td>
<td>
<span>d</span>
</td>
</tr>
</table>
one of the tables has header and one of them doesn't. and in your css you do not specify the table without header... you should has a code like this
table , tr, td{}
I have a question about a html table, i know a windows application that has this, a vertical scrollable table, but some columns are fixed on the page and others are always outside the page. I have a example:
The black border is the page, wich is responsive.
The red border is the table.
The green border is the part that is always fullscreen on the page,
always with The same columns.
The blue border is the part thats always off the screen with
information thats not required but if you need it you can scroll to
the right.
Anyone have an idea how to do this? In CSS? Or do i need Javascript for it?
My current code:
This class is attached to the tag.
/*MAIN TABLE*/
.tableMain {
font-size: 13px;
margin: 0;
padding: 0;
width: 200%;
table-layout: fixed;
}
But i think i need 2 classes, 1 on page class, and 1 off page class so i can define the columns that should be ouside the page. But i really dont know how to do that. Currently i've edited my headercells with this idea.
.tableCell, .tableHeaderCell{
width: 8.5%;
}
.tableSecondCell{
width: 150px;
}
This is my current HTML:
<table class='tableMain'>
<thead class='tableHeader'>
<tr class='tableHeaderRow'>
<th class='tableCell'>Name</th>
<th class='tableCell'>Email</th>
<th class='tableCell'>Role</th>
<th class='tableCell'>Username</th>
<th class='tableCell'>Department</th>
<th class='tableSecondCell'>Team</th>
<th class='tableSecondCell'>Web</th>
<th class='tableSecondCell'>App</th>
</tr>
</thead>
<tbody class='tableBody'>
<tr class='tableRow'>
<td class='tableCell'>User Name</td>
<td class='tableCell'>username1#example.com</td>
<td class='tableCell'>employee</td>
<td class='tableCell'>username1</td>
<td class='tableCell'>Support</td>
<td class='tableSecondCell'>Team1</td>
<td class='tableSecondCell'>True</td>
<td class='tableSecondCell'>True</td>
</tr>
</tbody>
</table>
Thanks for your time.
You can use instead below css for the table to scroll
.tableMain {
width: 100%;
max-width: 100%;
}
and wrap a div .table-responsive around table tag
.table-responsive {
min-height: .01%;
overflow-x: auto;
}
I have a dynamically built table that ends up with the below code (with example values):
<table id="patientTable" class="display" cellspacing="0" width="100%">
<thead id="TableHeader">
<tr>
<th>Value1</th>
<th>Value2</th>
<th>Value3</th>
</tr>
</thead>
<tbody id="tableContent">
<tr class="clickable row_0" onclick="selectPatient(10001);" id="10001" style="background: #FFF;">
<td class="tableContent">Value1</td>
<td class="tableContent">Value2</td>
<td class="tableContent">Value3</td>
</tr>
</tbody>
</table>
I am trying to highlight the row that is been hovered over using the below CSS:
.clickable :hover {
background-color: #CCC;
}
For some reason, this changes the background of what would be the "<td>" element, for example, will just highlight Value1, Value2 or Value3 rather than the entire row.
I have tried (to no avail) to use:
.clickable tr:hover {
background-color: #CCC;
}
.clickable:hover {
background-color: #CCC;
}
.tr:hover {
background-color: #CCC;
}
.tr :hover {
background-color: #CCC;
}
I find this unusual behaviour, as it appears to work for everyone else on every other example i've seen..
Worth Mentioning: The table is build from a complex system, that basically performs an AJAX request, which performs a PHP database query, takes the values, throws them into a JSON array, passes them back to JS, re-parses the array as JSON, loops through and creates the table, then outputs it. Could the JS be causing the issue?
The class name ".clickable", "row_#" (where # is a number) and the ID for the table row need to stay, as they are used in future functions and provide me with a way to identify each row individually.
One solution is to apply the hover on child elements td's when hover on parent tr:
.clickable:hover td {
background-color: #CCC;
}
<table id="patientTable" class="display" cellspacing="0" width="100%">
<thead id="TableHeader">
<tr>
<th>Value1</th>
<th>Value2</th>
<th>Value3</th>
</tr>
</thead>
<tbody id="tableContent">
<tr class="clickable row_0" onclick="selectPatient(10001);" id="10001" style="background: #FFF;">
<td class="tableContent">Value1</td>
<td class="tableContent">Value2</td>
<td class="tableContent">Value3</td>
</tr>
</tbody>
</table>
This works (from your question) :
.clickable:hover {
background-color: #CCC;
}
but why is there nothing happening when you hover then ?
because this rule is overwritten by the inline style: style="background: #FFF;"
Hint : NEVER write inline style (except if you REALLY need it)
if you remove style="background: #FFF;" everything will be fine.
Working example :
.clickable {
background-color: #FFF;
}
.clickable:hover {
background-color: #CCC;
}
<table id="patientTable" class="display" cellspacing="0" width="100%">
<thead id="TableHeader">
<tr>
<th>Value1</th>
<th>Value2</th>
<th>Value3</th>
</tr>
</thead>
<tbody id="tableContent">
<tr class="clickable row_0" onclick="selectPatient(10001);" id="10001">
<td class="tableContent">Value1</td>
<td class="tableContent">Value2</td>
<td class="tableContent">Value3</td>
</tr>
<tr class="clickable row_1" onclick="selectPatient(10002);" id="10002">
<td class="tableContent">Value1</td>
<td class="tableContent">Value2</td>
<td class="tableContent">Value3</td>
</tr>
</tbody>
</table>
Edit :
For more information about which CSS rule will have priority over others, see this article on MDN : https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
You can't colour table rows. Colour the table cells (th and td) instead, using the direct child selector (>).
Edit: Apollo (below) is right: Of course you can colour table rows, but if you want to colour the row with a hover, you need this (just like the answer that was given before):
tr:hover > td,
tr:hover > th {
background-color:#ccc;
}
I am using jQuery to reload data inside the tbody. However, the header column width keeps resizing event though I put the fixed width for the columns. I am using Firefox.
Simple HTML table:
<table style="width:95%;" border="1" align="center" >
<thead>
<tr>
<td class="header" style="width:20%">ProductFamily
<select onchange="selectCategoryChange()">
<option "1">1</option>
<option "2">2</option>
</select>
</td>
<td class="header" style="width:20%">ProductNum</td>
<td class="header" style="width:30%">ProductDesc</td>
<td class="header" style="width:5%">DT Rate</td>
<td class="header" style="width:5%">List Rate</td>
<td class="header" style="width:5%">Man Hour Unit</td>
<td class="header" style="width:5%">Precall</td>
<td class="header" style="width:5%">SOW</td>
<td class="header" style="width:5%">Box</td>
</tr>
</thead>
<tbody id="tbodyDataRow">
<!-- Data Rows Here -->
</tbody>
</table>
When the tbody.empty(), it automatically resizes the width of the header columns, which make the page looks ugly. and then when I reload the new rows, it resize it back to original width. Here is my Jquery code.
$(document).ready(function() {
selectCategoryChange = function()
{
var tbody = $("#tbodyDataRow");
tbody.empty();
};
});
This works, but I've not tested it in all browsers. Change HTML to:
<table border="1" align="center">
<thead>
<tr>
<th>ProductNum</th>
<th>Product</th>
<th>DT Rate</th>
<th>List Rate</th>
<th>Man Hour Unit</th>
<th>Precall</th>
<th>SOW</th>
<th></th>
</tr>
</thead>
<tbody id="tbodyDataRow">
<!-- tbody Content -->
</tbody>
</table>
You should avoid inline styles anyway. Add this CSS file:
table {
border: 1px solid black;
}
.header {
background-color: #ccc;
font-weight: bold;
min-width: 200px;
}
That'll fix your problem, but again it's not cross-browser tested. You might consider allowing the resize.
Final result Fiddle
Your table style="width:95%;" is the problem. You are expecting a table with 8 X 200px = 1600px width, but your table should has 95% as width, which can be more or less than 1600px. If it be deferent, the headers will be ajusted automatic. I'm sorry about my english.
I had a similar problem with empty() function applied on ul element.
HTML structure :
<table>
<tr>
<td>
<ul id="list"></ul>
</td>
<td>
...
</td>
</tr>
I have a JS timer which call an ajax function responsible to refresh the content of the list (ul). To update the list (ul) I started to empty it with the following code:
$("#list").empty();
At each iteration, the column width was incremented even if content was the same. I finally replaced the content by the initial content by using replaceWith function and this time it was ok:
$("#list").replaceWith('<ul id="list"></ul>');