I am using javascript to convert a large table to a pdf - javascript

I wrote this great script to help my team set up the weekly task distribution board, I wrote it using java script, html, and css, they've been doing it for a very long time in pencil on paper. but now i am in the final stage, i would like to convert my table to pdf, and this is where i found it difficult, i did several tests : like convert csv to pdf, it doesn't always give a good table, as it is under html. I would like to add a column at the end of the table for remarks but I think I will try with it later. now i'm just focus on pdf export. to be able to print our table every week and hang it, instead of pencil and a paper.
<table id="timetable">
<body>
<tr>
<td>
<link href="table.css" rel="stylesheet">
<script src="table.js"></script>
</td>
<tr>
<button onclick="exportCSV()">Export CSV</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script>
<button onclick="exportPDF()">Export PDF</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.77/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.77/vfs_fonts.js"></script>
</body>
const timetable = document.getElementById("timetable");
const days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
const hours = ["7H", "13H", "20H"];
// Create table headers for days
const daysHeaderRow = document.createElement("tr");
const daysHeaderCell = document.createElement("th");
daysHeaderCell.innerHTML = "Days";
daysHeaderRow.appendChild(daysHeaderCell);
days.forEach(day => {
const dayHeaderCell = document.createElement("th");
dayHeaderCell.innerHTML = day;
dayHeaderCell.colSpan = 3;
daysHeaderRow.appendChild(dayHeaderCell);
});
timetable.appendChild(daysHeaderRow);
// Create table headers for hours
const hoursHeaderRow = document.createElement("tr");
const hoursHeaderCell = document.createElement("th");
hoursHeaderCell.innerHTML = "Hours";
hoursHeaderRow.appendChild(hoursHeaderCell);
for (let i = 0; i < days.length; i++) {
for (let j = 0; j < 3; j++) {
const hourHeaderCell = document.createElement("th");
hourHeaderCell.innerHTML = hours[j];
hoursHeaderRow.appendChild(hourHeaderCell);
}
}
timetable.appendChild(hoursHeaderRow);
// Create row for Mina
const names = ["Khalfi","Redouani", "Daki", "Hamma", "Saadane", "Boughanem", "El Ansari","Badilou","Raoui", "Chouiba", "Dahmane", "Achdad", "Bouryal", "Ettouri", "Saadouni"];
for (let name of names) {
const row = document.createElement("tr");
const nameCell = document.createElement("td");
nameCell.innerHTML = name;
row.appendChild(nameCell);
for (let i = 0; i < days.length; i++) {
for (let j = 0; j < 3; j++) {
const cell = document.createElement("td");
const select = document.createElement("select");
select.classList.add("cell");
const options = [" ", "CP", "ME", "CL", "CE", "R"];
options.forEach(option => {
const optionElement = document.createElement("option");
optionElement.value = option;
optionElement.innerHTML = option;
select.appendChild(optionElement);
});
cell.appendChild(select);
row.appendChild(cell);
}
}
timetable.appendChild(row);
}
function exportCSV() {
var rows = document.querySelectorAll("#timetable tr");
var csvData = [];
for (var i = 0; i < rows.length; i++) {
var rowData = [];
var cells = rows[i].querySelectorAll("td, th");
for (var j = 0; j < cells.length; j++) {
const select = cells[j].querySelector("select");
if(select){
rowData.push(select.value);
}else{
rowData.push(cells[j].innerText);
}
}
csvData.push(rowData);
}
var csv = Papa.unparse(csvData);
var csvData = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
var csvURL = null;
if (navigator.msSaveBlob) {
csvURL = navigator.msSaveBlob(csvData, 'timetable.csv');
} else {
csvURL = window.URL.createObjectURL(csvData);
}
var tempLink = document.createElement('a');
tempLink.href = csvURL;
tempLink.setAttribute('download', 'timetable.csv');
tempLink.click();
// Convert the CSV data to a PDF and download it
var pdf = new jsPDF('l','mm','a4');
pdf.addPage();
pdf.text(csv, 10, 10);
pdf.save('timetable.pdf');
#timetable th {
border: 1px solid #ddd;
padding: 8px;
text-align: center;
background-color: #006699; /* bleu foncé /
}
#timetable tr:nth-child(even) {
background-color: #E6E6FA; / lavande */
}
/* Mise en page globale */
body {
background-color: #f1f1f1;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
/* Style de la barre de navigation */
nav {
background-color: #333;
color: #fff;
display: flex;
justify-content: space-between;
padding: 10px 20px;
}
nav a {
color: #fff;
text-decoration: none;
margin-right: 10px;
}
/* Style de la section principale */
main {
padding: 20px;
}
/* Style des titres */
h1, h2, h3 {
color: #333;
text-align: center;
margin-bottom: 20px;
}
/* Style des paragraphes */
p {
line-height: 1.5;
margin-bottom: 20px;
}
/* Style des images */
img {
max-width: 100%;
}

I see you already have pdfmaker available by your script so we can use that instead to convert your data to pdf with that instead.
You can achieve that with this download function:
function downloadPDFWithPDFMake() {
var rows = document.querySelectorAll("#timetable tr");
var data = [];
for (var i = 0; i < rows.length; i++) {
var rowData = [];
var cells = rows[i].querySelectorAll("td, th");
for (var j = 0; j < cells.length; j++) {
const select = cells[j].querySelector("select");
if(select){
rowData.push({text: select.value, style: 'tableData'});
}else{
rowData.push({text: cells[j].innerText, style: 'tableData'});
}
}
data.push(rowData);
}
var docDefinition = {
header: { text: 'Your awesome table', alignment: 'center' },
footer: function(currentPage, pageCount) { return ({ text: `Page ${currentPage} of ${pageCount}`, alignment: 'center' }); },
content: [
{
style: 'tableExample',
table: {
headerRows: 1,
body: [
...data
]
},
layout: {
fillColor: function(rowIndex) {
return (rowIndex % 2 === 0) ? '#E6E6FA' : null;
}
},
},
],
styles: {
tableExample: {
// table style
},
tableData: {
// table data style
},
},
};
pdfMake.createPdf(docDefinition).download('Your awesome table');
}
You have the hability to stylish on the configuration via the classes names. For a better info.

Related

How can i optimise javascript pagination so that it works for any number of pages?

i am trying to create Vanilla Javascript Pagination and i have a problem because it looks like my pagination is only working when there is 7 pages,when that number switches there are small bugs but i cant find a way to optimise better my code and to make the code be usable for any number of page.Here is the code:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous" />
<link rel="stylesheet" href="./main.css" />
</head>
<body>
<section class="blog-listing">
<div class="container">
<div class="row">
<div class="col-6">
<input
type="search"
class="inputs"
id="searcher"
placeholder="Search" />
<input type="hidden" name="type" value="BLOG_POST" />
<input type="hidden" name="type" value="LISTING_PAGE" />
</div>
<div class="col-6"></div>
</div>
<div class="row" id="blogs"></div>
<div id="blog-pagination"></div>
<div id="buttons"></div>
</div>
</section>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"></script>
<script src="./main.js"></script>
</body>
</html>
CSS
.blog-listing {
padding: 200px 0px;
}
.blog-listing input {
background-color: #f3f3f3;
border-radius: 40.5px;
width: 100%;
padding: 20px;
margin-bottom: 20px;
}
.blog-listing input::-moz-placeholder {
font-family: "Poppins";
font-weight: 300;
font-size: 18px;
line-height: 44px;
color: #19212f;
}
.blog-listing input:-ms-input-placeholder {
font-family: "Poppins";
font-weight: 300;
font-size: 18px;
line-height: 44px;
color: #19212f;
}
.blog-listing input::placeholder {
font-family: "Poppins";
font-weight: 300;
font-size: 18px;
line-height: 44px;
color: #19212f;
}
.blog-listing__card {
background: #ffffff;
box-shadow: 0px 0px 40px rgba(0, 0, 0, 0.105633);
border-radius: 4px;
padding-bottom: 100px;
margin-top: 50px;
}
.blog-listing__card__image img {
width: 100%;
}
.blog-listing__card__text {
padding: 30px 40px 60px;
}
.blog-listing__card__text a {
font-family: "Poppins";
font-weight: 700;
font-size: 16px;
line-height: 25px;
color: #089fd9;
}
.blog-listing__card__text p {
font-family: "Poppins";
font-weight: 700;
font-size: 16px;
line-height: 25px;
color: #878787;
padding-top: 15px;
}
.blog-listing__card__text h1,
.blog-listing__card__text h2,
.blog-listing__card__text h3 {
font-family: "Poppins";
font-weight: 700;
font-size: 22px;
line-height: 53px;
letter-spacing: -0.392857px;
color: #293241;
}
.blog-listing__card__divider {
border: 1px solid #cccccc;
}
.blog-listing__card.is-hidden {
opacity: 0;
}
.blog-listing__card__topics ul {
list-style-type: none;
}
.blog-listing__card__topics ul li a {
font-family: "Abel";
font-weight: 400;
font-size: 12px;
line-height: 25px;
color: #293241;
opacity: 0.5;
}
.blog-tag-filter {
background-color: transparent;
border: 0;
border-radius: 0;
padding: 0;
}
#media (max-width: 767px) {
.blog-tag-filter {
margin-bottom: 1.5rem;
text-align: center;
}
}
.blog-tag-filter__title {
color: #fff;
margin-right: 1.5rem;
}
.blog-tag-filter__select-wrapper {
display: inline-block;
max-width: 100%;
position: relative;
width: 100%;
}
.blog-tag-filter__select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
display: inline-block;
padding: 1.25rem 4.5rem 1.25rem 2.75rem;
background-color: #f3f3f3;
border-radius: 40.5px;
padding: 18px;
width: 100%;
max-width: 100%;
font-family: "Poppins";
font-weight: 300;
font-size: 18px;
color: #19212f;
}
.blog-tag-filter__select-wrapper:after {
color: #19212f;
content: "▾";
pointer-events: none;
position: absolute;
right: 0.7rem;
top: 50%;
transform: translateY(-50%);
}
#blog-pagination {
text-align: center;
padding: 50px 0px;
}
#buttons input {
display: inline-block;
cursor: pointer;
border: 0.75px solid #bbbbbb;
border-radius: 4px;
padding: 20px;
width: 100px;
text-align: center;
background-color: white;
color: #089fd9;
}
#buttons {
text-align: center;
}
.active {
background-color: #089fd9 !important;
color: #ffffff !important;
}
:disabled {
cursor: not-allowed !important;
color: gray !important;
background-color: #f1f1f1 !important;
}
.none {
display: none !important;
}
JS
let allBlogs = [];
allBlogs.length = 14;
let blog_div = document.getElementById("blogs");
let blogTagSelect = document.querySelector("#tag-select");
// let selectedItem = blogTagSelect.options[blogTagSelect.selectedIndex];
let countList = new Array();
let addPageList = new Array();
let presentPage = 1;
let countPerEachPage = 2;
let countOfPages = 0;
let buttons = document.getElementById("buttons");
function prepareList() {
let inputFirst = document.createElement("input");
inputFirst.setAttribute("type", "button");
inputFirst.setAttribute("id", "first");
inputFirst.setAttribute("value", "first");
inputFirst.onclick = function () {
presentPage = 1;
loadMyPaginationList();
for (let i = 0; i < pageBtns.length; i++) {
pageBtns[i].classList.remove("active");
if (Number(pageBtns[i].value) == presentPage) {
pageBtns[i].classList.add("active");
}
if (pageBtns[i].classList.contains("active")) {
pageBtns[i].classList.remove("none");
for (let j = 0; j < pageBtns.length; j++) {
if (pageBtns[j].value > 2) {
pageBtns[j].classList.add("none");
pageBtns[1].classList.remove("none");
if (pageBtns[j].value > pageBtns.length - 2) {
pageBtns[j].classList.remove("none");
}
}
}
}
}
};
let inputPrevious = document.createElement("input");
inputPrevious.setAttribute("type", "button");
inputPrevious.setAttribute("id", "previous");
inputPrevious.setAttribute("value", "previous");
inputPrevious.onclick = function () {
presentPage -= 1;
loadMyPaginationList();
for (let i = 0; i < pageBtns.length; i++) {
pageBtns[i].classList.remove("active");
if (Number(pageBtns[i].value) == presentPage) {
pageBtns[i].classList.add("active");
pageBtns[i].classList.remove("none");
if (Number(pageBtns[i].value) < Math.ceil(pageBtns.length / 2)) {
pageBtns[i + 2].classList.add("none");
}
if (Number(pageBtns[i].value) == pageBtns.length - 2) {
pageBtns[i - 1].classList.remove("none");
for (let j = 0; j < pageBtns.length; j++) {
if (pageBtns[j].value < Math.ceil(pageBtns.length / 2)) {
pageBtns[j].classList.add("none");
}
}
}
}
}
};
buttons.appendChild(inputFirst);
buttons.appendChild(inputPrevious);
for (count = 0; count < allBlogs.length; count++) {
countList.push(count);
}
countOfPages = getCountOfPages();
for (let i = 1; i <= countOfPages; i++) {
let inputButton = document.createElement("input");
inputButton.setAttribute("type", "button");
inputButton.setAttribute("class", "page-buttons");
inputButton.setAttribute("value", i);
inputButton.onclick = function () {
presentPage = Number(inputButton.value);
loadMyPaginationList();
};
buttons.appendChild(inputButton);
if (
inputButton.value > presentPage + 1 &&
inputButton.value < countOfPages - 1
) {
inputButton.classList.add("none");
if (Number(inputButton.value) == countOfPages - 2) {
let Dots = document.createElement("input");
Dots.setAttribute("value", "...");
Dots.setAttribute("class", "dots");
buttons.appendChild(Dots);
}
}
}
let inputNext = document.createElement("input");
inputNext.setAttribute("type", "button");
inputNext.setAttribute("id", "next");
inputNext.setAttribute("value", "next");
inputNext.onclick = function () {
presentPage += 1;
loadMyPaginationList();
for (let i = 0; i < pageBtns.length; i++) {
pageBtns[i].classList.remove("active");
if (Number(pageBtns[i].value) == presentPage) {
pageBtns[i].classList.add("active");
if (pageBtns[i + 1] != null) {
pageBtns[i + 1].classList.remove("none");
pageBtns[i - 1].classList.add("none");
}
if (Number(pageBtns[i].value - 1) >= Math.ceil(pageBtns.length / 2)) {
pageBtns[i - 1].classList.remove("none");
} else {
pageBtns[i - 1].classList.add("none");
}
if (pageBtns[i].classList.contains("active")) {
pageBtns[i].classList.remove("none");
if (pageBtns[i - 2] != null) {
pageBtns[i - 2].classList.add("none");
if (pageBtns[i].value > Math.ceil(pageBtns.length / 2 + 1)) {
pageBtns[i - 2].classList.remove("none");
}
}
}
}
}
};
let inputLast = document.createElement("input");
inputLast.setAttribute("type", "button");
inputLast.setAttribute("id", "last");
inputLast.setAttribute("value", "last");
inputLast.onclick = function () {
presentPage = countOfPages;
loadMyPaginationList();
for (let i = 0; i < pageBtns.length; i++) {
pageBtns[i].classList.remove("active");
if (Number(pageBtns[i].value) == presentPage) {
pageBtns[i].classList.add("active");
}
}
};
buttons.appendChild(inputNext);
buttons.appendChild(inputLast);
let pageBtns = document.querySelectorAll(".page-buttons");
for (let i = 0; i < pageBtns.length; i++) {
if (Number(pageBtns[i].value) == presentPage) {
pageBtns[i].classList.add("active");
}
pageBtns[i].addEventListener("click", function () {
let current = document.getElementsByClassName("active");
if (current.length > 0) {
current[0].classList.remove("active");
}
pageBtns[i].classList.add("active");
});
}
}
//function for creating how many how many number per each page
function getCountOfPages() {
return Math.ceil(countList.length / countPerEachPage);
}
//function for creating how to move between the pages
function loadMyPaginationList() {
let offset = (presentPage - 1) * countPerEachPage + 1 - 1;
let start = (presentPage - 1) * countPerEachPage;
let end = start + countPerEachPage;
addPageList = countList.slice(start, end);
createPageList();
validatePageCount();
}
//function for adding numbers to each page
function createPageList() {
blog_div.innerHTML = "";
let indexEnd =
presentPage * countPerEachPage <= allBlogs.length
? presentPage * countPerEachPage
: allBlogs.length;
for (let i = (presentPage - 1) * countPerEachPage; i < indexEnd; i++) {
let bootstrapDiv = document.createElement("div");
bootstrapDiv.classList = "col-lg-4 col-md-6 col-sm-12";
let card = document.createElement("div");
card.classList = "blog-listing__card";
let cardImage = document.createElement("div");
cardImage.classList = "blog-listing__card__image";
let link = document.createElement("a");
link.setAttribute("href", "#");
let img = document.createElement("img");
img.setAttribute("src", "./Bitmap.svg");
let cardText = document.createElement("div");
cardText.classList = "blog-listing__card__text";
let cardTitle = document.createElement("h2");
cardTitle.innerText = `Naslov ${i}`;
let textLink = document.createElement("a");
textLink.setAttribute("href", "#");
textLink.innerText = `Datum | Autor`;
let textText = document.createElement("p");
textText.innerText = `Opis`;
let topics = document.createElement("div");
topics.classList = "blog-listing__card__topics";
let topicList = document.createElement("ul");
let topicLi = document.createElement("li");
let topicLink = document.createElement("a");
topicLink.setAttribute("href", "#");
topicLink.innerText = `Tagovi`;
let divider = document.createElement("div");
divider.classList = "blog-listing__card__divider";
cardText.appendChild(cardTitle);
cardText.appendChild(textLink);
cardText.appendChild(textText);
link.appendChild(img);
cardImage.appendChild(link);
topicLi.appendChild(topicLink);
topicList.appendChild(topicLi);
topics.appendChild(topicList);
card.appendChild(cardImage);
card.appendChild(cardText);
card.appendChild(topics);
card.appendChild(divider);
bootstrapDiv.appendChild(card);
blog_div.appendChild(bootstrapDiv);
}
}
//function for validating real time condition like if move to last page, last page disabled etc
function validatePageCount() {
let inputFirst = document.getElementById("first");
let inputPrevious = document.getElementById("previous");
let inputNext = document.getElementById("next");
let inputLast = document.getElementById("last");
let PBtn = document.querySelectorAll(".page-buttons");
if (presentPage == 1) {
inputFirst.setAttribute("disabled", "");
inputPrevious.setAttribute("disabled", "");
} else {
inputFirst.removeAttribute("disabled");
inputPrevious.removeAttribute("disabled");
}
if (presentPage == countOfPages) {
inputNext.setAttribute("disabled", "");
inputLast.setAttribute("disabled", "");
} else {
inputNext.removeAttribute("disabled");
inputLast.removeAttribute("disabled");
}
}
//function for loading pagination functionality
function loadMyPagination() {
prepareList();
loadMyPaginationList();
}
window.onload = loadMyPagination;
function liveSearch() {
let searchQuery = document.getElementById("searcher").value;
let cards = document.querySelectorAll(".blog-listing__card");
for (let i = 0; i < cards.length; i++) {
if (cards[i].querySelector("h1, h2, h3").outerText !== null) {
if (
cards[i]
.querySelector("h1, h2, h3")
.outerText.toLowerCase()
.includes(searchQuery.toLowerCase())
) {
cards[i].classList.remove("is-hidden");
} else {
cards[i].classList.add("is-hidden");
}
}
}
}
let typingTimer;
let typeInterval = 300;
let searchInput = document.getElementById("searcher");
searchInput.addEventListener("keyup", () => {
clearTimeout(typingTimer);
typingTimer = setTimeout(liveSearch, typeInterval);
});
function blogFilter() {
if (document.querySelector("#tag-select") !== null) {
let blog_div = document.getElementById("blogs");
let blogTagSelect = document.querySelector("#tag-select");
let selectedItem = blogTagSelect.options[blogTagSelect.selectedIndex];
if (selectedItem.innerText == "Tags") {
blog_div.innerHTML = "";
for (let i = 0; i < allBlogs.length; i++) {
let bootstrapDiv = document.createElement("div");
bootstrapDiv.classList = "col-lg-4 col-md-6 col-sm-12";
let card = document.createElement("div");
card.classList = "blog-listing__card";
let cardImage = document.createElement("div");
cardImage.classList = "blog-listing__card__image";
let link = document.createElement("a");
link.setAttribute("href", "#");
let img = document.createElement("img");
img.setAttribute("src", "./Bitmap.svg");
let cardText = document.createElement("div");
cardText.classList = "blog-listing__card__text";
let cardTitle = document.createElement("h2");
cardTitle.innerText = `Naslov ${i}`;
let textLink = document.createElement("a");
textLink.setAttribute("href", "#");
textLink.innerText = `Datum | Autor`;
let textText = document.createElement("p");
textText.innerText = `Opis`;
let topics = document.createElement("div");
topics.classList = "blog-listing__card__topics";
let topicList = document.createElement("ul");
let topicLi = document.createElement("li");
let topicLink = document.createElement("a");
topicLink.setAttribute("href", "#");
topicLink.innerText = `Tagovi`;
let divider = document.createElement("div");
divider.classList = "blog-listing__card__divider";
cardText.appendChild(cardTitle);
cardText.appendChild(textLink);
cardText.appendChild(textText);
link.appendChild(img);
cardImage.appendChild(link);
topicLi.appendChild(topicLink);
topicList.appendChild(topicLi);
topics.appendChild(topicList);
card.appendChild(cardImage);
card.appendChild(cardText);
card.appendChild(topics);
card.appendChild(divider);
bootstrapDiv.appendChild(card);
blog_div.appendChild(bootstrapDiv);
}
} else {
blog_div.innerHTML = "";
for (let i = 0; i < allBlogs.length; i++) {
if (allBlogs[i].topic.includes(selectedItem.innerText)) {
let bootstrapDiv = document.createElement("div");
bootstrapDiv.classList = "col-lg-4 col-md-6 col-sm-12";
let card = document.createElement("div");
card.classList = "blog-listing__card";
let cardImage = document.createElement("div");
cardImage.classList = "blog-listing__card__image";
let link = document.createElement("a");
link.setAttribute("href", "#");
let img = document.createElement("img");
img.setAttribute("src", "./Bitmap.svg");
let cardText = document.createElement("div");
cardText.classList = "blog-listing__card__text";
let cardTitle = document.createElement("h2");
cardTitle.innerText = `Naslov ${i}`;
let textLink = document.createElement("a");
textLink.setAttribute("href", "#");
textLink.innerText = `Datum | Autor`;
let textText = document.createElement("p");
textText.innerText = `Opis`;
let topics = document.createElement("div");
topics.classList = "blog-listing__card__topics";
let topicList = document.createElement("ul");
let topicLi = document.createElement("li");
let topicLink = document.createElement("a");
topicLink.setAttribute("href", "#");
topicLink.innerText = `Tagovi`;
let divider = document.createElement("div");
divider.classList = "blog-listing__card__divider";
cardText.appendChild(cardTitle);
cardText.appendChild(textLink);
cardText.appendChild(textText);
link.appendChild(img);
cardImage.appendChild(link);
topicLi.appendChild(topicLink);
topicList.appendChild(topicLi);
topics.appendChild(topicList);
card.appendChild(cardImage);
card.appendChild(cardText);
card.appendChild(topics);
card.appendChild(divider);
bootstrapDiv.appendChild(card);
blog_div.appendChild(bootstrapDiv);
}
}
}
}
}
// blogTagSelect.addEventListener("change", blogFilter);
https://i.stack.imgur.com/M3H2N.png
I tried to optimise the code to work for all numbers of pages but I can't find a good solution
For the pagination numbers and links, try something like this:
//Element to append page numbers
let paginationElem = document.getElementbyId("yourPageElementIdHere")
//Your blogs
let allBlogs = []
//Get number of pages required
let pagesNeeded = allBlogs.length / <number of entries per-page> //May need to be rounded
//Create numbered link for each page. Begin loop at 0 to avoid printing first page as "0"
for(i=1; i < pagesNeeded + 1; i++) {
let pageNum = document.createElement("a").innerHTML = i
pageNum.html = "" //your link to page here
paginationElem.append(pageNum)
}
In case you're wondering how to select and display the relevant articles on each page, you'll need to get the clicked number of the page - as search param (?pageNum=4) in link, perhaps - then create a loop, which will store the correct articles in an array. Something like this should work:
//Your articles in an array
let allBlogs = []
let pageNum = //Get value from search param
// Array for articles to display on desired page
let articlesToDisplay = []
//Set default for first page
let firstArticle = 0
// Set number of first article/starting point for loop
if(pageNum != 0) {
firstArticle = (pageNum - 1) * 10 //or other number of articles per page
}
// Loop through articles, beginning at first article,for desired number of articles (10, here). Push into array.
for(i=firstArticle; i < firstArticle + 10; i++) {
articles.push(allBlogs[i])
}
You can loop through the articlesToDislay array, or create elements in the final loop and have these appended to somewhere in the document.

How could I select an image in a table and then copy it to another td in a diffrent table

I'm making a program that generates 2 tables. First has 16 images that represent a menu or options that you can click and then by clicking it you select in. The second table is generated by inputting rows and cells. So the second table is by default blank and each cells is meant to by replaced by an image that you selected in the first table. I've managed to do everything but I don't completley understand how to do the selecting and setting the image. (I assume it has something to do with ids and then onclick()?)
stolpci = window.prompt("vpiši stevilo stolpcov:");
for (i2 = 0; i2 < 1;) {
if (stolpci < 11 || stolpci > 41) {
stolpci = window.prompt("Napačno število. Število mora biti večje od 10 in manjše od 40. Ponovno vpiši stevilo stolpcov:");
} else {
i2++;
}
}
vrstice = window.prompt("vpiši stevilo vrstic:");
for (i2 = 0; i2 < 1;) {
if (vrstice < 6 || vrstice > 11) {
vrstice = window.prompt("Napačno število. Število mora biti večje od 5 in manjše od 11. Ponovno vpiši stevilo vrstic:");
} else {
i2++;
}
}
function generateTable() {
const tbl = document.createElement("table");
const tblBody = document.createElement("tbody");
for (let i = 0; i < vrstice; i++) {
const row = document.createElement("tr");
row.id = i;
for (let j = 0; j < stolpci; j++) {
const cell = document.createElement("td");
const cellText = document.createTextNode(' ');
cell.appendChild(cellText);
row.appendChild(cell);
cell.id = j;
}
tblBody.appendChild(row);
}
tbl.appendChild(tblBody);
document.body.appendChild(tbl);
}
function options() {
const tbl = document.createElement("table");
const tblBody = document.createElement("tbody");
let nImage = 1;
for (let i = 0; i < 1; i++) {
const row = document.createElement("tr");
for (let j = 0; j < 16; j++) {
const cell = document.createElement("td");
const cellText = document.createTextNode("");
if (nImage > 16) {
nImage = 1;
}
cell.style.backgroundImage = "url('images/sprite" + nImage + ".gif')";
cell.id = nImage;
nImage++;
cell.appendChild(cellText);
row.appendChild(cell);
}
tblBody.appendChild(row);
}
tbl.appendChild(tblBody);
document.body.appendChild(tbl);
}
window.onload = () => {
options();
generateTable();
}
table {
border: 1px solid gray;
padding: 0px;
margin: 0px;
border-spacing: 0px;
}
td {
margin: 0px;
padding: 0px;
min-width: 32px;
max-width: 32px;
max-height: 32px;
min-height: 32px;
width: 32px;
height: 32px;
border: 1px solid gray;
background-color: silver;
}
You would need to add click events to each cell. When click you could have another object which you save the 'selected' data to i.e the cell data. You would then need a button which when clicked would move your 'selected' data to the cells in the other table.

It is possible to create two table with js?

I am trying to create two tables and populate them with two randomized arrays. I don't remember how I got to this point but below is a codepen I have. I want to create a table class="side" and a table class="top" and put the random arrays in them. Please forgive me for the messy codes. I have no experience with coding and just want to make something for my students. Thank you.
edit1: cut the codes a little. I want to make a table with 3 cells in a column and another table with 4 cells in a row and randomly populate them with the two emojis array respectively. Can anyone help me with the JS codes?
<table class="top">
1
1
1
</table>
<table class="side">
2222
</table>
UPDATE:
Thanks to everyone for your input and advice. With the examples I was able to understand what my codes was lacking. I've posted it below for viewing and have hide the incomplete codes.
const animals = [
"🐕",
"🐈‍",
"🐄",
"🐐",
"🐎",
"🐖",
"🐇",
"🦆",
"🐔",
"🐁",
"🐑"
];
const fruits = [
"🍇",
"🍊",
"🍑",
"🥝",
"🍈",
"🍉",
"🥭",
"🍎",
"🍓",
"🍆",
"🥕",
"🥒",
"🫑",
"🧅",
"🍄"
];
function shuffle(a) {
let j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return a;
}
shuffle(animals);
let t1side = document.getElementsByClassName("tside").item(0);
for (let x = 0; x < 3; x++) {
let tr = document.createElement("tr");
for (let y = 0; y < 1; y++) {
let td = document.createElement("td");
{
td.setAttribute("id", "r" + (x + 1) + "d" + (y + 1));
td.appendChild(document.createTextNode(animals[x * 1 + y]));
}
tr.appendChild(td);
}
t1side.appendChild(tr);
}
shuffle(fruits);
let t2top = document.getElementsByClassName("ttop").item(0);
for (let x = 0; x < 1; x++) {
let tr = document.createElement("tr");
for (let y = 0; y < 4; y++) {
let td = document.createElement("td");
{
td.setAttribute("id", "r" + (x + 1) + "d" + (y + 1));
td.appendChild(document.createTextNode(fruits[x * 1 + y]));
}
tr.appendChild(td);
}
t2top.appendChild(tr);
}
* {
padding: 0;
margin: 0;
}
.top {
top: 0px;
left: 200px;
position: absolute;
}
.side {
top: 100px;
left: 0px;
position: absolute;
}
table.ttop ,table.ttop tr,table.ttop td {
height: 50px;
width: 100px;
padding: 0px;
marging: 0px;
background-color: pink;
font-size: 50px;
text-align: center;
border-collapse: collapse;
border: 0px solid none;
}
table.tside, table.tside tr, table.tside td {
height: 50px;
width: 50px;
padding: 0px;
marging: 0px;
background-color: yellow;
font-size: 80px;
text-align: center;
border-collapse: collapse;
border: 0px solid none;
}
<body>
<style>
</style>
<body>
<div class="top">
<table class="ttop">
</table>
</div>
<div class="side">
<table class="tside">
</table>
</div>
</body>
<script>
</script>
</body>
var spaces2 = [
"🐕",
"🐇",
"🦆",
"🐔",
"🐁",
"🐑"
];
var spaces = [
"🍇",
"🍊",
"🍑",
"🥝",
"🍈",
"🍉",
"🥭",
"🍎",
];
function shuffle(a) {
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return a;
}
shuffle(spaces2);
var tbody = document.getElementsByTagName("tbody").item(0);
for (var x = 0; x < 3; x++) {
var tr = document.createElement("tr");
for (var y = 0; y < 1; y++) {
var td = document.createElement("td");
{
td.setAttribute("id", "r" + (x + 1) + "d" + (y + 1));
td.appendChild(document.createTextNode(spaces2[x * 1 + y]));
}
tr.appendChild(td);
}
tbody.appendChild(tr);
}
shuffle(spaces);
var top = document.getElementsByClassName("top").item(0);
for (var x = 0; x < 1; x++) {
var tr = document.createElement("tr");
for (var y = 0; y < 4; y++) {
var td = document.createElement("td");
{
td.setAttribute("id", "r" + (x + 1) + "d" + (y + 1));
td.appendChild(document.createTextNode(spaces[x * 1 + y]));
}
tr.appendChild(td);
}
tbody.appendChild(tr);
}
* {
padding: 0;
margin: 0;
}
table.top tbody, tr, td {
height: 50px;
width: 50px;
padding: 0px;
marging: 0px;
background-color: none;
font-size: 40px;
text-align: center;
border-collapse: collapse;
border: 0px solid none;
}
table.side tbody, tr, td {
height: 50px;
width: 50px;
padding: 0px;
marging: 0px;
background-color: none;
font-size: 40px;
text-align: center;
border-collapse: collapse;
border: 0px solid none;
}
<body>
<style>
</style>
<body>
<div class="top">
<table id="top">
</table>
<div class="side">
<table id="side">
<tbody></tbody>
</table>
</div>
</body>
<script>
</script>
</body>
You want to generate tables from javaScript using an aYrray as content. Here is a small snippet of the generation of a table.
const spaces = [
"🍇",
"🍊",
"🍑",
"🥝",
"🍈",
"🍉",
"🥭",
"🍎",
"🍓",
"🍆",
"🥕",
"🥒",
"🫑",
"🧅",
"🍄"
];
function loadEvents() {
generateTable(spaces, "container", ["class1", "class2", "class3", "etc"]);
}
function generateTable(dataTable, containerId, classes) {
shuffle(dataTable);
let container = document.getElementById(containerId);
let table = document.createElement("table");
// Add classes to table
for (const clazz of classes) {
table.classList.add(clazz);
}
// Calculate cant of rows and columns
let cantDataRow = 0;
let cantDataCol = 0;
do {
cantDataRow++;
cantDataCol = Math.ceil(dataTable.length / cantDataRow);
} while (dataTable.length / Math.pow(cantDataRow, 2) > 1);
let aux = 0;
for (let i = 0; i < cantDataRow; i++) { // rows
let row = document.createElement("tr");
for (let j = 0; j < cantDataCol; j++) { // columns
let col = document.createElement("td");
col.textContent = dataTable[aux++];
row.appendChild(col); // Add column to row
}
table.appendChild(row); // Add row to table
}
container.appendChild(table); // Add table to container
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
addEventListener("DOMContentLoaded", loadEvents);
table, tr, td{
border: 1px solid black;
border-collapse: collapse;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div id="container"></div>
<script src="script.js"></script>
</body>
</html>
You would only have to call the function passing it the array with the data of the table, the container of the table and the classes that you want it to contain.
It is not necessary to create the shuffle function twice. It is created only once and can be called infinitely many times. I recommend using let instead of var.
Nice question :-) You only need one loop for each table. I did it with a for loop. I added a function that outputs a random image.
const t1 = document.querySelector('.top');
const t2 = document.querySelector('.side');
const spaces2 = [
"🐕",
"🐇",
"🦆",
"🐔",
"🐁",
"🐑"
];
const spaces = [
"🍇",
"🍊",
"🍑",
"🥝",
"🍈",
"🍉",
"🥭",
"🍎",
];
let tr = document.createElement('tr');
for (let i = 0; i < 3; i++) {
let td = document.createElement('td');
td.innerHTML = getRandomElement(spaces2);
tr.append(td);
}
t1.append(tr);
// t2
for (let i = 0; i < 4; i++) {
let tr = document.createElement('tr');
let td = document.createElement('td');
td.innerHTML = getRandomElement(spaces);
tr.append(td);
t2.append(tr);
}
function getRandomElement(items) {
return items[Math.floor(Math.random()*items.length)];
}
small {
font-size: 16px;
padding-left:5px;
}
table {
}
table td {
border: 2px solid #999;
padding: 5px;
}
<h2>Table 1<small>3 cols and 1 row</small></h2>
<table class="top"></table>
<h2>Table 2<small>1 cols with 4 rows</small></h2>
<table class="side"></table>

How can I create a multi-option dynamic dropdown in a table?

I am trying to make a dynamic multi-select option dropdown. The text for the options element in the dropdown are coming from a database that I am fetching. I want each row in the table to have the last column contain this multi-select option dropdown. Right now, the result is it's skipping every row and only on the last row is it displaying all the options multiple times (as amount of times as there are rows). So instead of showing in each row, every row is empty expect the last one and the values are all being showed in the final row. Also, strangely it created empty white space on the right side of the table, like it make new columns. I have attached an image to help visualize this.
How do I display the options properly in each row and how do I make it a multi select dropdown, where if the user clicks one of the options, that option is added to the impact area section.
Thanks.
Image: Image of how it currently looks
Javascript:
//Get Resources and corresponding information and display it in a table
function getResources(){
fetch("______", {
}).then(data => {
var table = document.getElementById("productivity-table");
for(var i=0; i < data.length; i++){
var row = table.insertRow(table.rows.length - 1);
var cell3 = row.insertCell(2);
cell3.classList.add("table-data");
//Cell3 - Create ul and li
var impact_ul = document.createElement("ul");
var impact_li = document.createElement("li");
impact_li.innerHTML = data[i].entity;
impact_li.setAttribute("style", "list-style-type:none");
//Add delete button row
var delete_span = document.createElement("span");
delete_span.className = "delete";
delete_span.innerHTML = "×"
impact_li.appendChild(delete_span);
impact_ul.appendChild(impact_li);
cell3.appendChild(impact_ul);
//Cell5 - Create department dropdown
var dep_dropdown = document.createElement('select');
console.log("dep dropdown", dep_dropdown);
//dep_dropdown.length = 0;
let dep_default = document.createElement('option');
dep_default.text = 'Select Department';
dep_default.disabled = true;
dep_dropdown.add(dep_default);
dep_dropdown.selectedIndex = 0;
fetch("______", {
}).then(data =>{
for(var i=0; i < data.length; i++){
var cell5 = row.insertCell(4);
cell5.classList.add("table-data");
var dep_option = document.createElement('option');
dep_option.text = data[i].dept_name;
dep_option.value = data[i]._id;
dep_dropdown.appendChild(dep_option);
cell5.appendChild(dep_dropdown);
}
}).catch(function(err) {
console.log('Fetch problem: ' + err);
});
}
})
}
here is what you asked for take alook on the snippet
window.onload = function() {
var data = ["option1", "option2", "option3", "option4"];
var table = document.getElementById("productivity-table");
function addslct(dep_dropdown) {
dep_dropdown = document.createElement('select');
dep_dropdown.size = "3";
dep_dropdown.className = "dep_select";
dep_dropdown.id = 'selection';
dep_dropdown.name = 'data options';
dep_dropdown.multiple = "multiple";
dep_dropdown.style.position = "relative";
dep_dropdown.style.width = "100%";
dep_dropdown.style.textAlign = "center";
dep_dropdown.style.color = "darkblue";
return dep_dropdown;
}
function addopts(data) {
var slcts = document.getElementsByClassName('dep_select');
for (var i = 0; i < slcts.length; i++) {
for (var a = 0; a < data.length; a++) {
slcts[i].options.add(optns(data[a], data[a]));
}
}
}
function optns(option, oname) {
var option = document.createElement('option');
option.Value = option;
option.textContent = oname;
return option;
}
table.rows[0].innerHTML += "<th>4</th>";
for (var i = 1; i < table.rows.length; i++) {
var newell = table.rows[i].cells.length;
table.rows[i].insertCell(newell);
table.rows[i].cells[table.rows.length - 1].appendChild(addslct());
}
addopts(data);
document.querySelectorAll('.dep_select').forEach(selectedOptions => {
selectedOptions.addEventListener('click', function() {
var col2 = this.options;
for (var o = 0; o < col2.length; o++) {
var o2 = col2[o];
if (o2.selected == true) {
var rwi = this.parentNode.parentNode.rowIndex;
var cli = this.parentNode.cellIndex;
var cell2 = table.rows[rwi].cells[cli-2];
var slctdopt = o2.value;
if (cell2.innerText.includes(slctdopt) == true) {
var excludez = cell2.innerText.replace("[ "+ slctdopt +" ]", "");
cell2.innerText = excludez + " [ " + slctdopt +" ]";
//cell2.innerText += " [ " + slctdopt +" ]";
} else {
excludez = slctdopt;
cell2.innerText += " [ "+ excludez +" ]";
}
}
}
});
});
}
#productivity-table {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#productivity-table td,
#productivity-table th {
border: 1px solid #ddd;
padding: 8px;
}
#productivity-table td {
text-align: center;
color: blue;
margin: auto;
width:20%;
}
#productivity-table tr:nth-child(even) {
background-color: #f2f2f2;
}
#productivity-table tr:hover {
background-color: #ddd;
}
#productivity-table th {
padding-top: 12px;
padding-bottom: 12px;
text-align: center;
background-color: #4CAF50;
color: white;
}
<table class="table1" id="productivity-table">
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
<tr>
<td>first</td>
<td></td>
<td>third</td>
</tr>
<tr>
<td>first</td>
<td>[ option2 ]</td>
<td>third</td>
</tr>
<tr>
<td>first</td>
<td>[ option3 ]</td>
<td>third</td>
</tr>
</table>

How to save active class to localstorage and keep when reloading in javascript

Is there any way to store toggled/activated item using localstorage and reload it?
I'm building a habit tracker and want the selected stars stay active when reloading the page.
So I tried localstorage.setItem with queryselectorAll, but it's not working.
Also tried stringify but only empty array was saved to localstorage.
let today = new Date();
let currentMonth = today.getMonth();
let currentYear = today.getFullYear();
const trackerBody = document.querySelector(".js-tracker-body");
function showTracker(month, year) {
const selectedDate = new Date(year, month);
const lastDate = new Date(
selectedDate.getFullYear(),
selectedDate.getMonth() + 1,
0
);
let date = 1;
for (let i = 0; i < 6; i++) {
const row = document.createElement("tr");
for (let j = 0; j < 6; j++) {
if (date <= lastDate.getDate()) {
const cell = document.createElement("td");
const cellPtag = document.createElement("p");
const cellText = document.createTextNode(date);
const cellIcon = document.createElement("i");
cell.setAttribute("class", "habit-count");
cellIcon.setAttribute("class", "fas fa-star star-icon");
cellPtag.appendChild(cellText);
cell.appendChild(cellPtag);
cell.appendChild(cellIcon);
row.appendChild(cell);
date++;
} else {
break;
}
}
trackerBody.appendChild(row);
}
}
showTracker(currentMonth, currentYear);
document.body.addEventListener("click", e => {
if (e.target.closest(".fa-star")) {
e.target.classList.toggle('selected');
}
saveSelectedTracker();
});
function saveSelectedTracker() {
const selectedTracker = document.querySelectorAll('.selected');
localStorage.setItem('selected', selectedTracker);
}
.tracker {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #fff;
background-color: #413f63;
}
.tracker-head {
margin-bottom: 30px;
text-align: center;
}
.date-picker {
margin-bottom: 10px;
display: flex;
justify-content: center;
align-items: center;
}
.previous,
.next {
padding: 0 20px;
font-size: 17px;
}
.monthAndYear {
font-size: 36px;
font-weight: 300;
}
.habit-content {
font-size: 16px;
font-weight: 300;
}
.tracker-items {
font-size: 20px;
text-align: center;
}
tr {
display: flex;
}
.habit-count {
padding: 0 10px 15px 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.habit-count:last-child {
padding-right: 0;
}
.habit-count p {
margin-bottom: 5px;
font-size: 14px;
}
.star-icon {
font-size: 30px;
color: #c2b7b0;
}
.selected {
color: #f4df21;
}
<div class="wrapper">
<div class="tracker">
<div class="tracker-head">
<div class="date-picker">
<a class="previous" onclick="previous()">
<i class="fas fa-chevron-left"></i>
</a>
<strong class="monthAndYear"></strong>
<a class="next" onclick="next()">
<i class="fas fa-chevron-right"></i>
</a>
</div>
<h1 class="js-habit-content habit-content"></h1>
</div>
<div class="tracker-main">
<table class="traker-items">
<thead></thead>
<tbody class="js-tracker-body"></tbody>
</table>
</div>
</div>
</div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/js/all.min.js"
integrity="sha256-HkXXtFRaflZ7gjmpjGQBENGnq8NIno4SDNq/3DbkMgo="
crossorigin="anonymous"
></script>
function showTracker(month, year) {
const selectedDate = new Date(year, month);
const lastDate = new Date(
selectedDate.getFullYear(),
selectedDate.getMonth() + 1,
0
);
monthAndYear.innerHTML = `${months[month]} ${year}`;
trackerBody.innerHTML = "";
let date = 1;
for (let i = 0; i < 6; i++) {
const row = document.createElement("tr");
for (let j = 0; j < 6; j++) {
if (date <= lastDate.getDate()) {
const cell = document.createElement("td");
const cellPtag = document.createElement("p");
const cellText = document.createTextNode(date);
const cellIcon = document.createElement("i");
cell.setAttribute("class", "habit-count");
cellIcon.setAttribute("class", "fas fa-star star-icon");
cellPtag.appendChild(cellText);
cell.appendChild(cellPtag);
cell.appendChild(cellIcon);
row.appendChild(cell);
date++;
} else {
break;
}
}
trackerBody.appendChild(row);
}
}
showTracker(currentMonth, currentYear);
document.body.addEventListener("click", e => {
if (e.target.closest(".fa-star")) {
e.target.classList.toggle('selected');
}
saveSelectedTracker();
});
function saveSelectedTracker() {
const selectedTracker = document.querySelectorAll('.selected');
localStorage.setItem('selected', selectedTracker);
}
I think the issue is that you're saving references to the actual elements on the page, vs data about which items are selected. Try changing it so that you save an array of identifiers for which items are selected, and then on page load looked for that list and reapplied the selected class to those.
You can do a quick check that your .setItem is working by hardcoding a simple string vs the variable you're currently using.
Perhaps try setting the index (value of j) into the cellIcon, like this:
cellIcon.setAttribute("data-index", j);
then in saveSelectedTracker get all the selected cells as you are doing, but save the index of j instead.
const selectedTracker = document.querySelectorAll('.selected');
const starredIndexes = [];
selectedTracker.forEach(function(item) {
starredIndexes.push(item.getAttribute('data-index'));
});
localStorage.setItem('selected', JSON.stringify(starredIndexes));
then in your showTracker method, pull out the array from local storage, deserialize and use the array to check if the star should be marked with the css class selected.
const starredIndexes = JSON.parse(localStorage.getItem('selected'))
//in your forloop
if(starredIndexes && Array.isArray(starredIndexes) && starredIndexes.indexOf(j) !== -1){
cellIcon.setAttribute("class", "fas fa-star star-icon selected"); //mark ones saved in local storage
}else{
cellIcon.setAttribute("class", "fas fa-star star-icon");
}
I think this would accomplish the gist of what you are trying to do. Let me know if you have any questions.
You should not try to store the elements themselves in the localStorage; instead, store their indexes.
const stars = document.querySelectorAll('.fa-star > path');
let stored = localStorage.getItem("selected") || '[]'
let indexes = JSON.parse(stored)
for(const index of indexes){
stars[index].classList.add('selected');
}
document.body.addEventListener("click", e => {
if (e.target.closest(".fa-star")) {
e.target.classList.toggle('selected');
}
saveSelectedTracker();
});
function saveSelectedTracker() {
const indexes = [];
for(let i = 0; i < stars.length; i++){
if(stars[i].classList.contains("selected")){
indexes.push(i);
}
}
console.log(indexes);
localStorage.setItem('selected', JSON.stringify(indexes));
}
Working Demo

Categories