convert rows of html table into bootstrap cards - javascript

I have html table with rows like below:
<table id="tb" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>title</th>
<th>price</th>
<th>discount</th>
<th>image</th>
</tr>
</thead>
<tbody>
<tr>
<td>PRODUCT 1</td>
<td align="right">24.43</td>
<td align="right">53</td>
<td>https://images-na.ssl-images-amazon.com/images/I/81xV%2BD1OkGL._AC_SL1500_.jpg</td>
</tr>
<tr>
<td>PRODUCT 2</td>
<td align="right">50.27</td>
<td align="right">70</td>
<td>https://images-na.ssl-images-amazon.com/images/I/61d-BO4sARL._AC_SL1500_.jpg</td>
</tr>
<!-- ... many other rows -->
<!-- I added this script to put the image link inside src -->
<script>
$('#tb td:nth-child(4n)').each((i, el) => {
$(el).wrapInner(`<img src="${el.innerText}" class="img-fluid"/>`);
});
</script>
I want to convert each row to a bootstrap card
I tried to give each the bootstrap class class="card" using jquery:
$('#tb tr').addClass("card")
it didn't worked, returns each row on top of each other
I want results like this:

It's pretty hard to take HTML code and use javascript to convert that into some other complicated format. If you want to do everything manually, you can make the cards by hand with HTML. However, I suggest using a database and PHP to programmatically create those cards or tables with the data in the database.
Here is some information about how to create those Bootstrap cards: https://getbootstrap.com/docs/4.0/components/card/
Here is some information about how to use databases and PHP to create those cards automatically: https://www.phpzag.com/create-bootstrap-cards-with-php-and-mysql/

The thing which you are trying to achieve makes no sense. I myself came across this dilemma of converting a table into a card but after some quick search I got to know, this makes no sense.
Think of it like transformers. Table and card are two different transformers and they cannot be converted into each other until and unless we you brute force.

You can convert the table into cards. I have done this in the WordPress admin tables. Though I have not done it into bootstrap.
Here is a way to do with straight CSS.
First remove the table header and footer (if you have one).
thead, tfoot {
display: none;
}
Then remove the background of the table
table {
background: none !important;
border: none !important;
}
Change your rows so that they display as a card:
make them inline-block so they will appear on the same row but as a full container
add a background, border, padding and shadow to style it
tr {
display: inline-block;
padding: 1rem 0.5rem 1rem 0.5rem;
margin: 1.5rem;
border: 1px solid grey;
border-radius 10px;
box-shadow: 0 0 10px;
}
Make the cells appear on their own rows
td {
display: block;
}
If you want to add labels to the cell data you can use ::before and use a specific CSS attribute selector. For example, in my WordPress admin tables the column names are added to each cell with the attribute "data-colname".
td[data-colname="Guardian"]::before {
content: "Guardian :";
}
Here is an example of my WordPress table as cards:
(And as you can imagine, you can't easily alter a WordPress admin table -- you work with what you get).

Don't need to write single line of CSS code for hide thead or tfoot. first you need to know about replaceWith() method in jQuery & replace() method in JavaScript. So just pull the table contents as a string and run a simple string replace. And add Bootstrap classes as you want for card design.
Helpful Links
https://stackoverflow.com/a/9230045/7052927
https://api.jquery.com/replacewith/
https://www.w3schools.com/jsref/jsref_replace.asp
$(document).ready(function () {
$("#tb thead, #tb tfoot").remove(); //Remove element
$("#tb").find('td').removeAttr("align"); // Remove attribute
$('#tb').replaceWith($('#tb').html()
.replace(/<tbody/gi, "<div id='tb' class='row row-cols-2 row-cols-md-3 row-cols-lg-4 g-3' ")
.replace(/<tr/gi, "<div class='col'> <div class='card'> <div class='card-body text-center' ")
.replace(/<\/tr>/gi, "</div></div></div>")
.replace(/<td/gi, "<div")
.replace(/<\/td>/gi, "</div>")
.replace(/<\/tbody/gi, "<\/div")
);
// each loop for card layout
$("#tb .card").each(function() {
$(this).find('.card-body div:first-child').addClass('h6 fw-bold text-primary'); // Change product style
var imgPath = $(this).find('.card-body div:last-child');
$(this).find('.card-body').before(`
<div class="ratio ratio-4x3">
<img src="`+ imgPath.text()+`" class="card-img-top1 p-2 w-auto mx-auto start-0 end-0" alt="...">
</div>
`);
imgPath.remove() // After pick text then remove
});
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container py-3">
<table id="tb" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>title</th>
<th>price</th>
<th>discount</th>
<th>image</th>
</tr>
</thead>
<tbody>
<tr>
<td>PRODUCT 1</td>
<td align="right">24.43</td>
<td align="right">53</td>
<td>https://images-na.ssl-images-amazon.com/images/I/81xV%2BD1OkGL._AC_SL1500_.jpg</td>
</tr>
<tr>
<td>PRODUCT 2</td>
<td align="right">50.27</td>
<td align="right">70</td>
<td>https://images-na.ssl-images-amazon.com/images/I/61d-BO4sARL._AC_SL1500_.jpg</td>
</tr>
</tbody>
</table>
</div>

Related

Puppeteer - thead overlapping on page break ONLY when thead is cut off by footer on previous page

What I am trying to do?
I am using Puppeteer to convert raw HTML to PDF. I have saved the HTML code in a file, and I'm reading from that file and converting it to PDF.
What is the problem
The thead is NOT overlapping on every page, NO.
It is ONLY overlapping when a thread has multiple rows and half of it gets cut off because of the page break. On the next page, the remainder of the thead is printed ALONG with the overlapped entire thead.
Here is the Output of the converted PDF Overlapping thead
<table id='TblCustomerRating' class='display unbreakable' border='1' cellspacing='0' cellpadding='0'
style=' width: 100%;border-collapse:collapse;'>
<thead>
<tr>
<th class='Greyheader' align="center" style="padding-top: 5px; padding-bottom: 5px;" colspan="4">Askari
Cement Limited</th>
</tr>
<tr>
<th class='Greyheader' align="center" style="padding-top: 5px; padding-bottom: 5px;" colspan="4">External
Rating</th>
</tr>
<tr class='Greyheader'>
<th width="12%" align="center" class='Greyheader'><b> ECAI</b> </th>
<th width="12%" align="center" class='Greyheader'><b>Long Term</b></th>
<th width="12%" align="center" class='Greyheader'><b>Short Term</b></th>
<th style='display:none' width="12%" align="center" class='Greyheader'><b>Rating Date</b></th>
</tr>
</thead>
<tbody>
<tr id="4" type="data" LT="" ST="" MT="" class=" GreyBorder">
<td width="10%" agencyCode='4' class='GreyBorder'
style='background-color:lightgray;text-align: center;padding-top: 5px;padding-bottom: 5px;font-weight: bold;width:10%;'>
JCR-VIS</td>
<td width="10%" RsCode='35' class='GreyBorder' align="center">A</td>
<td width="10%" RsCode='' class='GreyBorder' align="center"></td>
<td align="center" style='display:none' class='GreyBorder'></td>
</tr>
</tbody>
</table><br />
What I have tried?
I have tried adding the following CSS: (it didn't work)
table { overflow: visible !important; }
thead { display: table-header-group !important; }
tr { page-break-inside: avoid !important; }
NOTE:
I repeat, the overlapping is not occurring when the table rows are cut off from page-break. It is ONLY overlapping when thead is cut off because of the page break. as shown in the image above.
Puppeteer version
1.19.0
Node.js version
v16.13.0
npm version
8.1.0
What operating system are you seeing the problem on?
Windows
I think I had the same issue. It is when you have a repeating table header (thead { display: table-header-group }) and the table breaks for printing between tr tags within thead. I couldn't find a way to do it with only the break-after, break-before or break-inside properties. This is a bit of a hack, but here is how I fixed it:
:root {
--header-height: 60px;
}
th {
break-inside: avoid;
}
thead th::after {
content: '';
display: block;
height: var(--header-height);
margin-bottom: -var(--header-height);
break-inside: avoid;
}
The height and negative margin-bottom are equal to the height of the tr elements below the first tr. In my code I just have 60px and -60px hard coded in, but I wanted to be clear that depending on the height of your table header that you will have to change those values. The height creates the size of element that can't be broken inside by a page break and the negative margin-bottom brings back up the table content so that it is not impacted by the existence of the pseudo-element. It essentially forces the header to be on the next page.
face the same problem.
You may put the content of <td> into <div> tag.

How can I protect the cell borders when hiding the table cells contents dynamically using plain javascript?

I am creating a table in plain JavaScript, and filling it up using onClick listener event in two ways - either clicking on a external button, or clicking on one of the cells itself; and in both ways, calling a function to randomly assign values to some of the cells. I am not able to hide the contents of my table cells using either of the methods available- display: none, and visibility: hidden. But I am still able to do it using fontSize = 0., wherin another problem crops-up viz the cells borders are lost. Thus my problem is that I want to hide my table cells contents whilst rendering values in them withput affecting the table structure.
I have already tried conventional methods available viz.
1) td {display: none;}, and td {visibilty: hidden}
2) I have also tried inline CSS style method to hide the cell contents, but all these methods blank the table itself i.e. oblivate the cell borders themselves.
3) When I use:
document.getElementById('myelement').getElementsByTagName('td')[n[i]].style.fontSize = 0; I am able to hide the contents, but then cell borders are lost.
<body>
<div class="container-fluid">
<table id="myelement">
<tr>
<td> </td>
... .... ...
<td> </td>
</tr>
</table>
</div>
</body>
<script>
...
for(let i=0;i<mycount;i++){
td[n[i]].firstChild.nodeValue='X';
document.getElementById('myelement').getElementsByTagName('td')
[n[i]].style.fontSize = 0;
}
...
</script>
All the techniques available blank the table itself i.e. oblivate the cell borders themselves. The expected result is intact table structure when hiding the cells contents.
Something like this?
Cell with class="hidden" will appear to be empty but you can change background: #fff; to any other color you want
td.hidden {
position: relative;
}
td.hidden:after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #fff;
z-index: 10;
}
<table border=1>
<tr>
<td class="hidden">asd</td>
<td>zxc</td>
<td>test</td>
</tr>
<tr>
<td>asd</td>
<td class="hidden">zxc</td>
<td>test</td>
</tr>
<tr>
<td>asd</td>
<td>zxc</td>
<td class="hidden">test</td>
</tr>
</table>

change table column width

I'm using react library that constructs table in the following template:
<div class="table-container" style="width:100%">
<table style="width:100%">
<thead>
<tr>
<th>BLA_Column</th>
</tr>
</thead>
</table>
<table style="width:100%">
<tbody>
<tr>
<td>BLA_Body</td>
</tr>
</tbody>
</table>
</div>
I'm able to set the width of the th and the td to auto, but, the result is that I get two different sizes (one for the th and one for the td).
When I try to use the following selector (for example), nothing happens:
table > thead > th {
width: 100px;
}
Also when I try to change directly the width using the chrome dev-tools, there is no change at all.
Thanks ahead!
CSS character > select only direct childs. Change your CSS with :
table > thead th {
width: 100px;
}
or
table > thead > tr > th {
width: 100px;
}

How to dynamically modify CSS class using Javascript / jQuery with wrapper?

I have an existing html code of table.
eg.
<div class="content-entry">
<table class="old-style" border="3">
<tr align="middle">
<td style="font-weight:bold"></td>
</tr>
</table>
</div>
I would like to conditionally remove all attributes/classes of the current table with the injection of a wrapper <div> and apply css class style to override the existing table behavior using Javascript / jQuery.
conten-entry might have multiple table blocks, and I would like to apply the same style change to all of them.
to:
<div class="content-entry">
<div class="responsive-table">
<table class="table table-bordered table-condensed">
<tr>
<td></td>
</tr>
</table>
</div>
</div>
How can I do this without changing the original html code?
Use .wrap, wraps an HTML structure around each element in the set of matched elements
$('.old-style').wrap('<div class="responsive-table"></div>').removeClass().addClass('table table-bordered table-condensed');
.responsive-table {
color: red;
}
.table {
font-weight: bold;
}
.table-bordered {
border: 2px solid black;
}
.table-condensed>tbody>tr>td,
.table-condensed>tbody>tr>th,
.table-condensed>tfoot>tr>td,
.table-condensed>tfoot>tr>th,
.table-condensed>thead>tr>td,
.table-condensed>thead>tr>th {
padding: 5px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="content-entry">
<table class="old-style">
<tr>
<td>Hello</td>
</tr>
</table>
</div>
Note: Calling .removeClass with no arguments will remove all of the item's classes.

Removing whitespace in collapse row

Bootply: http://www.bootply.com/N8lH48VBN7
I have rows where I want each row to expand to show additional rows but I'm having trouble getting rid of the whitespace even when the hidden row is not expanded. I think there might be a way to write a function in JS, but is there a faster and easier way to do this?
Also, when the collapsed rows are expanded, there is some whitespace, and I tried to change some properties of the div to no avail.
Bootstrap has a css style itself.
(so, if you want to apply your css style, you have to use '!important' keyword in your css.)
and, your code structure is not good as well.
therefore, it made a little space inside of each table row.
I think you want to do like this. :)
[RESULT] http://www.bootply.com/0QqWzFcwWo#
1. HTML Source
<div class="col-lg">
<div class="project" id="prodemo"></div>
<table class="table table-striped table-hover">
<thead align="center">
<tr>
<th width="1%"> </th>
<th width="24%">ID</th>
<th width="25%">Name</th>
<th width="25%">Phone</th>
<th width="25%">DOB</th>
</tr>
</thead>
<tbody>
<!-- [demo] -->
<tr class="prevent_drag" data-target="#demo" data-toggle="collapse">
<td> </td>
<td>MyID</td>
<td>MyName</td>
<td>MyPhone</td>
<td>MyDOB</td>
</tr>
<tr id="demo" class="collapse myOptions">
<td> </td>
<td>Details</td>
<td>Details2</td>
<td>Details3</td>
<td>Details4</td>
</tr>
<!-- [demo2] -->
<tr class="prevent_drag" data-target="#demo2" data-toggle="collapse">
<td> </td>
<td>MyID</td>
<td>MyName</td>
<td>MyPhone</td>
<td>MyDOB</td>
</tr>
<tr id="demo2" class="collapse myOptions">
<td> </td>
<td>Details</td>
<td>Details2</td>
<td>Details3</td>
<td>Details4</td>
</tr>
<!-- [demo3] -->
<tr class="prevent_drag" data-target="#demo3" data-toggle="collapse">
<td> </td>
<td>MyID</td>
<td>MyName</td>
<td>MyPhone</td>
<td>MyDOB</td>
</tr>
<tr id="demo3" class="collapse myOptions">
<td> </td>
<td>Details</td>
<td>Details2</td>
<td>Details3</td>
<td>Details4</td>
</tr>
</tbody>
</table>
</div>
2. CSS source
.myOptions {
padding: 0 !important;
margin: 0 !important;
color: red;
}
.table th {
cursor:default;
}
.prevent_drag {
cursor:pointer;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
See this bootply
Just add this css and stay away from !important as other answers suggest.
.table>tbody>tr>td[colspan] {
padding: 0;
}
.table>tbody>tr>td[colspan] .table {
margin-bottom: 0;
}
Never use !important
Almost all answers here suggest to use !important. I think all of them need to read about CSS Specificity and stop using !important today.
...Or you could add this JS code:
$("td[colspan]").css("padding", "0");
$(".table").css("margin-bottom", "0");
Here is the Bootyply
Or can use pure CSS like this:
td[colspan]{
padding:0 !important;
}
.table{
margin-bottom:0 !important;
}
CSS Only Bootply
Use below code in css
tr td{padding: 0!important;}
Thanks With Regards
Remove padding-top and padding-bottom only from your collapsed rows. This padding is coming from bootstrap table style.
tr:not([data-toggle]) > td { padding-top: 0px; padding-bottom: 0px; }
Selecting the cells which are children of rows which do not carry an attribute called data-toggle.
There is margin in the nested table as well. You can remove that:
.table tr:not([data-toggle]) table,
.table tr:not([data-toggle]) td {
padding: 0; margin: 0px;
}
Use this CSS style
tr[data-toggle="collapse"] + tr td {
padding: 0 !important;
}

Categories