#!/usr/bin/perl
use strict;
use warnings;
# HTML Template
my $html_template = <<'HTML';
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Table and Pie Chart with Tabs</title>
<link rel="stylesheet" href="https://c...content-available-to-author-only...e.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<script src="https://c...content-available-to-author-only...r.net/npm/chart.js"></script>
<script src="https://c...content-available-to-author-only...r.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
<style>
/* Default Light Mode */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
color: #333;
transition: all 0.3s ease;
}
header {
width: 100%;
text-align: center;
padding: 20px 0;
font-size: 24px;
font-weight: bold;
background-color: #fff;
color: #333;
}
.container {
display: flex;
justify-content: space-between;
padding: 20px;
}
.table-container {
flex: 1;
margin-right: 20px;
}
.chart-container {
width: 400px;
height: 400px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
table, th, td {
border: 1px solid #ddd;
}
th, td {
padding: 8px 12px;
text-align: left;
}
th {
background-color: #f4f4f4;
}
canvas {
width: 200px;
height: 200px;
}
.tabs {
display: flex;
margin-top: 20px;
justify-content: center;
}
.tab {
padding: 10px 20px;
margin: 0 5px;
cursor: pointer;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f4f4f4;
text-align: center;
}
.tab:hover {
background-color: #ddd;
}
.tab-content {
display: none;
margin-top: 20px;
padding: 20px;
border: 1px solid #ddd;
border-top: none;
}
.active-tab {
background-color: #ccc;
}
.active-content {
display: block;
}
.active-row {
background-color: #e0f7fa;
}
/* Dark Mode Styles */
.dark-mode {
background-color: #333;
color: #fff;
}
.dark-mode header {
background-color: #444;
color: #fff;
}
.dark-mode .tab {
background-color: #444;
color: #fff;
border: 1px solid #555;
}
.dark-mode .tab:hover {
background-color: #555;
}
.dark-mode table, .dark-mode th, .dark-mode td {
border: 1px solid #555;
}
.dark-mode th {
background-color: #666;
}
.dark-mode .tab-content {
background-color: #444;
color: #fff;
}
.dark-mode .active-row {
background-color: #555;
}
/* Dark Mode Button (Icon version) */
.dark-mode-toggle {
position: absolute;
top: 20px;
right: 20px;
background-color: transparent;
border: none;
cursor: pointer;
font-size: 24px;
color: #fff;
transition: background-color 0.3s ease, color 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
border-radius: 50%;
padding: 5px;
}
/* Light Mode Icon */
.dark-mode-toggle.light-mode i {
color: #ffeb3b; /* Yellow sun icon for light mode */
}
/* Hover Effect for Light Mode (Sun) */
.dark-mode-toggle.light-mode:hover {
background-color: #fff;
}
.dark-mode-toggle.light-mode:hover i {
color: #ffea00; /* Lighter yellow when hovered */
}
/* Dark Mode Icon (Moon) */
.dark-mode-toggle.dark-mode i {
color: #fff; /* White crescent icon in dark mode */
}
/* Hover Effect for Dark Mode (Moon) */
.dark-mode-toggle.dark-mode:hover {
background-color: #444; /* Blends with the dark background */
}
.dark-mode-toggle.dark-mode:hover i {
color: #fff;
}
/* Chart.js Legend Text (Dark Mode Fix) */
.dark-mode .chartjs-legend li {
color: #fff !important; /* Ensure legend text is visible in dark mode */
}
/* "Back to Top" Button */
.back-to-top {
position: fixed;
bottom: 20px;
right: 20px;
background-color: transparent;
border: none;
cursor: pointer;
font-size: 24px;
color: #fff;
transition: background-color 0.3s ease, color 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
border-radius: 50%;
padding: 5px;
opacity: 0; /* Initially hidden */
visibility: hidden; /* Initially hidden */
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.back-to-top.show {
opacity: 1;
visibility: visible;
}
.back-to-top i {
color: #00bcd4; /* Light cyan color for the arrow */
}
/* Hover Effect for "Back to Top" Button */
.back-to-top:hover {
background-color: #00bcd4;
color: #fff;
}
.back-to-top:hover i {
transform: scale(1.1);
}
</style>
</head>
<body>
<header>Table and Pie Chart with Tab</header>
<div class="container">
<!-- Table Section -->
<div class="table-container">
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
<tbody>
%TABLE_ROWS%
</tbody>
</table>
</div>
<!-- Pie Chart Section -->
<div class="chart-container">
<canvas id="pieChart"></canvas>
</div>
</div>
<!-- Tabs Section -->
<div class="tabs">
%TABS%
</div>
<!-- Tab Content -->
%TAB_CONTENTS%
<!-- Dark Mode Toggle Button -->
<button id="darkModeToggle" class="dark-mode-toggle light-mode">
<i class="fas fa-sun"></i>
</button>
<!-- Back to Top Button -->
<button class="back-to-top" id="backToTopBtn">
<i class="fas fa-arrow-up"></i>
</button>
<script>
// Pie Chart Data
const data = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple'],
datasets: [{
data: [300, 50, 100, 40, 120],
hoverOffset: 4
}]
};
const config = {
type: 'pie',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1500,
easing: 'easeInOutCubic',
animateRotate: true,
animateScale: true,
},
plugins: {
legend: {
position: 'top',
labels: {
color: '#333',
}
},
datalabels: {
anchor: 'center',
align: 'center',
font: {
weight: 'bold',
size: 14,
},
color: '#fff',
formatter: (value, context) => {
let total = context.dataset._meta[Object.keys(context.dataset._meta)[0]].total;
let percentage = ((value / total) * 100).toFixed(1);
return `${value} (${percentage}%)`;
}
}
}
}
};
const pieChart = new Chart(document.getElementById('pieChart'), config);
// Dark Mode Fix for Chart.js Legend Text
const updateChartLegendForDarkMode = () => {
if (document.body.classList.contains('dark-mode')) {
// Change the legend label color to white in dark mode
pieChart.options.plugins.legend.labels.color = '#fff';
pieChart.update();
} else {
// Reset the legend label color to black for light mode
pieChart.options.plugins.legend.labels.color = '#333';
pieChart.update();
}
};
// Scroll to top functionality
const backToTopBtn = document.getElementById('backToTopBtn');
window.onscroll = () => {
if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 100) {
backToTopBtn.classList.add('show');
} else {
backToTopBtn.classList.remove('show');
}
};
backToTopBtn.onclick = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};
// Tab Switching Functionality with Table Row Sync
const tabs = document.querySelectorAll('.tab');
const contents = document.querySelectorAll('.tab-content');
const tableRows = document.querySelectorAll('tbody tr');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const targetTab = tab.getAttribute('data-tab');
// Hide all tab contents
contents.forEach(content => content.classList.remove('active-content'));
tabs.forEach(tab => tab.classList.remove('active-tab'));
tableRows.forEach(row => row.classList.remove('active-row'));
// Show the clicked tab content
document.getElementById(targetTab).classList.add('active-content');
// Mark the clicked tab as active
tab.classList.add('active-tab');
// Highlight the corresponding table row
const correspondingRow = document.querySelector(`tr[data-tab="${targetTab}"]`);
correspondingRow.classList.add('active-row');
});
});
// Table Row Click to Open Corresponding Tab
tableRows.forEach(row => {
row.addEventListener('click', () => {
const targetTab = row.getAttribute('data-tab');
const tab = document.querySelector(`.tab[data-tab="${targetTab}"]`);
// Trigger the tab click to highlight the tab and row
tab.click();
});
});
// Dark Mode Toggle Functionality
const toggleButton = document.getElementById('darkModeToggle');
toggleButton.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
updateChartLegendForDarkMode();
const icon = document.querySelector('.dark-mode-toggle i');
if (document.body.classList.contains('dark-mode')) {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
toggleButton.classList.remove('light-mode');
toggleButton.classList.add('dark-mode');
} else {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
toggleButton.classList.remove('dark-mode');
toggleButton.classList.add('light-mode');
}
});
</script>
</body>
</html>
HTML
# Sample data for the table (can be dynamic)
my @table_data = (
{ id => 1, name => "John Doe", age => 28, city => "New York" },
{ id => 2, name => "Jane Smith", age => 34, city => "Los Angeles" },
{ id => 3, name => "Sam Johnson", age => 25, city => "Chicago" },
);
# Generate table rows
my $table_rows = '';
foreach my $row (@table_data) {
$table_rows .= "<tr data-tab=\"tab$row->{id}\">\n";
$table_rows .= "<td class=\"tab-id\">$row->{id}</td>\n";
$table_rows .= "<td>$row->{name}</td>\n";
$table_rows .= "<td>$row->{age}</td>\n";
$table_rows .= "<td>$row->{city}</td>\n";
$table_rows .= "</tr>\n";
}
# Generate tabs
my $tabs = '';
for (my $i = 1; $i <= 7; $i++) {
$tabs .= "<div class=\"tab\" data-tab=\"tab$i\">Tab $i</div>\n";
}
# Generate tab contents
my $tab_contents = '';
for (my $i = 1; $i <= 7; $i++) {
$tab_contents .= "<div class=\"tab-content\" id=\"tab$i\">\n";
$tab_contents .= "<p>This is content for Tab $i.</p>\n";
$tab_contents .= "</div>\n";
}
# Replace placeholders in the template
$html_template =~ s/%TABLE_ROWS%/$table_rows/g;
$html_template =~ s/%TABS%/$tabs/g;
$html_template =~ s/%TAB_CONTENTS%/$tab_contents/g;
# Output the final HTML
print header
(-type
=> 'text/html', -charset
=> 'UTF-8');