Secure Password Generator

Secure Password Generator

Your New Password

Customize

Password Security Guide

${topic.content}

`; // Content is already HTML-safe accordionItem.appendChild(button); accordionItem.appendChild(panel); accordionContainer.appendChild(accordionItem); button.addEventListener('click', () => { button.classList.toggle('spg-active'); panel.classList.toggle('spg-active'); if (panel.classList.contains('spg-active')) { panel.style.maxHeight = panel.scrollHeight + "px"; } else { panel.style.maxHeight = null; } }); }); } // --- Generator Logic --- function handleGeneration() { const length = parseInt(lengthSlider.value, 10); const useUpper = checkUpper.checked; const useLower = checkLower.checked; const useNumbers = checkNumbers.checked; const useSymbols = checkSymbols.checked; let charset = ""; let guaranteedChars = []; let numSets = 0; if (useUpper) { charset += CHARSETS.UPPER; guaranteedChars.push( CHARSETS.UPPER[ Math.floor(Math.random() * CHARSETS.UPPER.length) ] ); numSets++; } if (useLower) { charset += CHARSETS.LOWER; guaranteedChars.push( CHARSETS.LOWER[ Math.floor(Math.random() * CHARSETS.LOWER.length) ] ); numSets++; } if (useNumbers) { charset += CHARSETS.NUMBERS; guaranteedChars.push( CHARSETS.NUMBERS[ Math.floor(Math.random() * CHARSETS.NUMBERS.length) ] ); numSets++; } if (useSymbols) { charset += CHARSETS.SYMBOLS; guaranteedChars.push( CHARSETS.SYMBOLS[ Math.floor(Math.random() * CHARSETS.SYMBOLS.length) ] ); numSets++; } if (charset === "") { passwordOutput.value = "Select at least one set!"; updateStrength(0, 0); return; } let password = [...guaranteedChars]; const remainingLength = length - password.length; for (let i = 0; i < remainingLength; i++) { password.push( charset[Math.floor(Math.random() * charset.length)] ); } // Shuffle the array to mix guaranteed chars const finalPassword = shuffleArray(password).join(""); passwordOutput.value = finalPassword; updateStrength(length, numSets); } function updateStrength(length, numSets) { let score = 0; if (length >= 12) score++; if (length >= 16) score++; if (numSets >= 3) score++; if (numSets === 4) score++; if (length >= 20 && numSets === 4) score++; strengthIndicator.className = "spg-strength-indicator"; // Reset if (score <= 1) { strengthIndicator.classList.add("spg-weak"); strengthIndicator.style.width = "25%"; } else if (score <= 3) { strengthIndicator.classList.add("spg-medium"); strengthIndicator.style.width = "60%"; } else { strengthIndicator.classList.add("spg-strong"); strengthIndicator.style.width = "100%"; } } function updateLengthLabel() { if(lengthValue) { lengthValue.textContent = lengthSlider.value; } } function copyPassword() { if (!navigator.clipboard) { // Fallback for insecure contexts passwordOutput.select(); document.execCommand('copy'); copyBtn.textContent = "Copied!"; } else { navigator.clipboard.writeText(passwordOutput.value).then(() => { copyBtn.textContent = "Copied!"; }).catch(err => { console.error("SPG: Could not copy text: ", err); copyBtn.textContent = "Error"; }); } setTimeout(() => { copyBtn.textContent = "Copy"; }, 1500); } // --- PDF Download Function --- if (pdfDownloadBtn) { pdfDownloadBtn.addEventListener("click", () => { if ( typeof window.jspdf === "undefined" || typeof window.jspdf.jsPDF === "undefined" ) { alert( "Error: PDF library (jsPDF) is not loaded. Please check your internet connection." ); return; } if (typeof window.jspdf.plugin.autotable === "undefined") { alert( "Error: PDF library (jsPDF-AutoTable) is not loaded. Please check your internet connection." ); return; } generatePDF(); }); } function generatePDF() { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const primaryColor = getComputedStyle(container).getPropertyValue( "--spg-primary-color" ) || "#0d6e6e"; const headStyles = { fillColor: primaryColor, textColor: "#ffffff", fontStyle: "bold", }; // Title doc.setFont("helvetica", "bold"); doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text("Generated Password Report", 105, 20, { align: "center", }); // Security Warning doc.setFont("helvetica", "bold"); doc.setFontSize(12); doc.setTextColor(var(--spg-danger-color, "#d32f2f")); doc.text("SECURITY WARNING:", 15, 35); doc.setFont("helvetica", "normal"); doc.setFontSize(10); doc.text("This document contains a password in plain text. Please destroy this file securely after use. Do not email or save it to a shared or public device.", 15, 42, { maxWidth: 180 }); // 1. Password Table const passHead = [["Generated Password"]]; const passBody = [[passwordOutput.value]]; doc.autoTable({ startY: 55, head: passHead, body: passBody, theme: "grid", headStyles: headStyles, bodyStyles: { font: "courier", fontSize: 12, fontStyle: 'bold' } }); // 2. Settings Table let lastY = doc.autoTable.previous.finalY; const settingsHead = [["Setting", "Value"]]; const settingsBody = [ ["Password Length", lengthSlider.value], ["Include Uppercase (A-Z)", checkUpper.checked ? "Yes" : "No"], ["Include Lowercase (a-z)", checkLower.checked ? "Yes" : "No"], ["Include Numbers (0-9)", checkNumbers.checked ? "Yes" : "No"], ["Include Symbols (!@#...)", checkSymbols.checked ? "Yes" : "No"], ]; doc.autoTable({ startY: lastY + 10, head: settingsHead, body: settingsBody, theme: "striped", headStyles: headStyles }); doc.save("Password-Report.pdf"); } // --- Utility Functions --- function escapeHTML(str) { if (!str) return ""; return str .toString() .replace(/&/g, "&") .replace(//g, ">") .replace(/"g, """) .replace(/'g, "'"); } function shuffleArray(array) { let newArr = [...array]; for (let i = newArr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [newArr[i], newArr[j]] = [newArr[j], newArr[i]]; } return newArr; } // --- Event Listeners --- if (lengthSlider) { lengthSlider.addEventListener("input", () => { updateLengthLabel(); handleGeneration(); }); } if (generateBtn) { generateBtn.addEventListener("click", handleGeneration); } if (copyBtn) { copyBtn.addEventListener("click", copyPassword); } [checkUpper, checkLower, checkNumbers, checkSymbols].forEach(el => { if(el) { el.addEventListener("change", handleGeneration); } }); // --- Initial Load --- populateGuide(); handleGeneration(); // Generate a password on load updateNavButtons(); // Set initial state } // --- End of initializePasswordGenerator() function --- /* * This new logic checks if the page is already loaded (common in Elementor). * If it is, it runs the setup function immediately. * If it's still loading (rare), it waits for the DOM event. */ if ( document.readyState === "complete" || document.readyState === "interactive" ) { // DOM is already ready, run the function now. initializePasswordGenerator(); } else { // Still loading, wait for the event document.addEventListener( "DOMContentLoaded", initializePasswordGenerator ); }