Investment Carbon Footprint Calculator
Your Investment Portfolio
This is the total value of your investment portfolio.
Add Holdings (Simulated Companies)
Select a simulated company and specify the amount invested in it. You can add multiple holdings.
Current Holdings:
The sum of individual investment amounts should ideally match your 'Total Portfolio Value' for accurate calculation. If it doesn't, the tool will use the sum of your individual investments as the total portfolio value for calculation purposes.
Carbon Footprint Analysis
Add holdings and click "Calculate Footprint" to see results.
Emissions Breakdown by Holding
Calculate the footprint to generate charts.
Weighted Average Carbon Intensity (WACI): Measures your portfolio's exposure to carbon-intensive companies, normalized by revenue. A lower number is generally better.
Total Financed Emissions (Absolute): Represents the total amount of greenhouse gas emissions (in tonnes of COâ‚‚ equivalent) that your investment is proportionally responsible for, based on the ownership stake in the companies.
Disclaimer: All company data and emissions figures are simulated for illustrative purposes only and do not reflect real-world values. This tool is for educational use and should not be used for actual financial or environmental decisions.
`; resultsOutput.innerHTML = tableHtml; } /** * Renders the emissions breakdown chart. * @param {Object} results - The calculated carbon footprint results. */ function renderEmissionsChart(results) { if (!results || !results.individualEmissionsBreakdown || results.individualEmissionsBreakdown.length === 0) { chartPlaceholder.classList.remove('hidden'); if (emissionsChartInstance) { emissionsChartInstance.destroy(); emissionsChartInstance = null; } return; } chartPlaceholder.classList.add('hidden'); // Hide placeholder if chart can be rendered const ctx = document.getElementById('emissionsChart').getContext('2d'); // Destroy existing chart instance if it exists to prevent overlap if (emissionsChartInstance) { emissionsChartInstance.destroy(); } // Prepare data for the chart const chartLabels = results.individualEmissionsBreakdown.map(h => h.symbol); const chartData = results.individualEmissionsBreakdown.map(h => h.financedEmissions); // Generate dynamic colors for the bars const backgroundColors = chartLabels.map((_, i) => `hsl(${i * (360 / chartLabels.length)}, 70%, 70%)`); const borderColors = chartLabels.map((_, i) => `hsl(${i * (360 / chartLabels.length)}, 70%, 50%)`); emissionsChartInstance = new Chart(ctx, { type: 'bar', data: { labels: chartLabels, datasets: [{ label: 'Financed Emissions (tCOâ‚‚e)', data: chartData, backgroundColor: backgroundColors, borderColor: borderColors, borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: 'top', labels: { font: { size: 14, family: 'Inter', }, color: '#333' } }, title: { display: true, text: 'Financed Emissions Breakdown by Company Holding', font: { size: 18, family: 'Inter', weight: 'bold' }, color: '#1F2937' }, tooltip: { callbacks: { label: function(context) { let label = context.dataset.label || ''; if (label) { label += ': '; } if (context.parsed.y !== null) { label += `${context.parsed.y.toFixed(2)} tCOâ‚‚e`; } return label; } } } }, scales: { y: { beginAtZero: true, title: { display: true, text: 'Financed Emissions (tCOâ‚‚e)', font: { size: 14, family: 'Inter' }, color: '#333' }, ticks: { font: { family: 'Inter' } } }, x: { title: { display: true, text: 'Company Symbol', font: { size: 14, family: 'Inter' }, color: '#333' }, ticks: { font: { family: 'Inter' } } } } } }); } /** * Handles the PDF download functionality. * Captures the results output and chart canvas to generate a PDF report. */ window.downloadPdf = async function() { // Ensure jsPDF and html2canvas libraries are loaded if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { displayMessage('PDF generation libraries not loaded. Please try again or refresh.'); return; } hideMessage(); // Clear any existing messages const { jsPDF } = jspdf; const doc = new jsPDF('p', 'pt', 'a4'); // 'p' for portrait, 'pt' for points, 'a4' for A4 size // Define the elements to be captured for the PDF report const elementsToCapture = [ document.getElementById('resultsOutput'), document.getElementById('emissionsChart') ]; let yPos = 40; // Initial Y position for content in the PDF // Add a main title to the PDF report doc.setFontSize(22); doc.setTextColor(51, 51, 51); // Dark gray doc.text('Investment Carbon Footprint Report', doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 30; // Move down for next element // Add generation date doc.setFontSize(12); doc.setTextColor(100, 100, 100); // Medium gray doc.text(`Generated on: ${new Date().toLocaleDateString()}`, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 40; // Move down for next element // Iterate through the captured canvases and add them to the PDF for (const element of elementsToCapture) { try { // Temporarily make the element visible if it's currently hidden const wasHidden = element.classList.contains('hidden'); if (wasHidden) { element.classList.remove('hidden'); } const canvas = await html2canvas(element, { scale: 2, // Increase scale for better resolution in PDF useCORS: true, // Required for images/fonts loaded from other origins if any backgroundColor: '#ffffff' // Ensure white background for captured content }); // Restore hidden state if it was temporarily made visible if (wasHidden) { element.classList.add('hidden'); } const imgData = canvas.toDataURL('image/png'); // Convert canvas to PNG data URL const imgWidth = 550; // Desired width for the image in the PDF (A4 is approx 595pt wide) const imgHeight = (canvas.height * imgWidth) / canvas.width; // Maintain aspect ratio // Check if the image fits on the current page. If not, add a new page. if (yPos + imgHeight > doc.internal.pageSize.getHeight() - 40) { // Check against a 40pt bottom margin doc.addPage(); // Add a new page yPos = 40; // Reset Y position for the new page } // Add the image to the PDF, centered horizontally doc.addImage(imgData, 'PNG', (doc.internal.pageSize.getWidth() - imgWidth) / 2, yPos, imgWidth, imgHeight); yPos += imgHeight + 30; // Move Y position down, adding some padding } catch (error) { console.error('Error capturing element for PDF:', error); displayMessage('Failed to generate part of the PDF. Please ensure all data is loaded.'); } } // Save the generated PDF file doc.save('Investment_Carbon_Footprint_Report.pdf'); }; // Initial setup: Populate company select and show the input tab when the DOM is ready populateCompanySelect(); renderHoldingsList(); // Render empty list initially showTab('input'); });