Problem 2: Truncated Axis
The Problem: The bar chart's Y-axis doesn't start at 0. This exaggerates the differences between values, creating a misleading sense of volatility.
The Solution: Start the Axis at Zero
Bar charts must start their value axis at zero to provide an honest, proportional representation of the data.
Problem 3: The "Spaghetti" Chart
The Problem: Plotting too many lines on one chart creates a tangled, unreadable mess.
The Solution: Small Multiples or Highlighting
Break the data into smaller charts, or use color to highlight one series at a time, keeping others grayed out for context.
`;
const pieFixCtx = document.getElementById('bdv-pie-fix')?.getContext('2d');
new Chart(pieFixCtx, { type: 'bar', data: { labels: bdv_data.pie.map(d=>d.label), datasets: [{ label: 'Market Share', data: bdv_data.pie.map(d=>d.value), backgroundColor: '#28a745' }] }, options: { indexAxis: 'y', plugins: { legend: {display: false} } } });
const barFixCtx = document.getElementById('bdv-bar-fix')?.getContext('2d');
new Chart(barFixCtx, { type: 'bar', data: { labels: bdv_data.bar.map(d=>d.label), datasets: [{ label: 'Performance Score', data: bdv_data.bar.map(d=>d.value), backgroundColor: '#28a745' }] }, options: { scales: { y: { beginAtZero: true } }, plugins: { legend: {display: false} } } });
const lineFixCtx = document.getElementById('bdv-line-fix')?.getContext('2d');
const highlightedLineData = JSON.parse(JSON.stringify(bdv_data.line));
highlightedLineData.datasets.forEach((ds) => { ds.borderColor = (ds.label === 'Brand A') ? 'blue' : 'lightgray'; });
new Chart(lineFixCtx, { type: 'line', data: highlightedLineData, options: { plugins: { title: { display: true, text: 'Highlighting a Single Brand' } } } });
}
function bdv_renderConfiguration() {
const container = document.getElementById('bdv-config-content');
if (!container) return;
const createTable = (key, title, col1, col2) => {
let tableHtml = `
${title}
| ${col1} | ${col2} | Action |
`;
bdv_data[key].forEach((row, index) => {
tableHtml += `| ${row.label} | ${row.value} | |
`;
});
tableHtml += `
`;
return tableHtml;
};
container.innerHTML = createTable('pie', 'Pie Chart Data', 'Label', 'Value') + createTable('bar', 'Bar Chart Data', 'Label', 'Value');
}
window.bdv_saveConfigData = () => {
['pie', 'bar'].forEach(key => {
const table = document.getElementById(`bdv-config-${key}`);
if (!table) return;
const rows = table.querySelectorAll('tbody tr');
let newData = [];
rows.forEach(row => {
let newRow = {
label: row.cells[0].textContent,
value: parseFloat(row.cells[1].textContent) || 0
};
newData.push(newRow);
});
bdv_data[key] = newData;
});
};
window.bdv_addRow = (key) => {
if(key==='pie') bdv_data.pie.push({label: 'New', value: 10});
if(key==='bar') bdv_data.bar.push({label: 'New', value: 850});
bdv_renderConfiguration();
};
window.bdv_deleteRow = (btn, key) => {
const table = document.getElementById(`bdv-config-${key}`);
btn.closest('tr').remove();
};
// --- UI & Navigation ---
window.bdv_openTab = (evt, tabId) => {
document.querySelectorAll("#bdv-container .bdv-tab-content").forEach(c => c.classList.remove('active'));
document.querySelectorAll("#bdv-container .bdv-tab-link").forEach(l => l.classList.remove('active'));
document.getElementById(tabId)?.classList.add('active');
evt.currentTarget.classList.add('active');
};
window.bdv_navigateTabs = (direction) => {
const tabs = Array.from(document.querySelectorAll('#bdv-container .bdv-tab-link'));
const activeTabIndex = tabs.findIndex(tab => tab.classList.contains('active'));
const nextTabIndex = (direction === 'next') ? (activeTabIndex + 1) % tabs.length : (activeTabIndex - 1 + tabs.length) % tabs.length;
tabs[nextTabIndex].click();
};
window.bdv_downloadPDF = () => {
const activeTabContent = document.querySelector('.bdv-tab-content.active > div');
if (!activeTabContent || activeTabContent.parentElement.id === 'bdv-config') {
alert("PDF download is not available for the data entry tab."); return;
}
const { jsPDF } = window.jspdf;
const title = "Data Visualization Report - " + document.querySelector('.bdv-tab-link.active').textContent;
html2canvas(activeTabContent, { scale: 2, useCORS: true }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const imgProps = pdf.getImageProperties(imgData);
const imgHeight = (imgProps.height * (pdfWidth - 20)) / imgProps.width;
pdf.setFontSize(18);
pdf.text(title, pdfWidth / 2, 15, { align: 'center' });
pdf.addImage(imgData, 'PNG', 10, 25, pdfWidth - 20, imgHeight);
pdf.save("Data-Visualization-Report.pdf");
});
};
bdv_init();
});