Homeowners Association Rule Compliance Checker

Homeowners Association Rule Compliance Checker

Describe Your Project

Compliance Analysis

Describe your project and click "Check Compliance" to see relevant HOA rules.

Customize HOA Rules

CategoryRule TextKeywords (comma-separated)Action

Add New Rule

Your project matches the following HOA rules. Please review them carefully.

`; listHtml = `
    ${rules.map(r => `
  • ${r.category}: ${r.text}
  • `).join('')}
`; } else { status = 'compliant'; bannerHtml = `

Likely Compliant

No specific rules found matching your project description. It's always best to double-check the official HOA documents.

`; listHtml = ''; } resultsContent.innerHTML = bannerHtml + `
${listHtml}
`; } function renderConfigTable() { configTbody.innerHTML = ruleData.map(r => ` `).join(''); } window.addRule = function() { const category = document.getElementById('new-rule-category').value; const text = document.getElementById('new-rule-text').value; const keywords = document.getElementById('new-rule-keywords').value; if (!category || !text || !keywords) { alert('Please fill all fields to add a new rule.'); return; } ruleData.push({ id: Date.now(), category, text, keywords: keywords.split(',').map(k => k.trim()) }); renderConfigTable(); populateControls(); document.getElementById('new-rule-category').value = ''; document.getElementById('new-rule-text').value = ''; document.getElementById('new-rule-keywords').value = ''; } window.updateRule = function(element) { const { id, prop } = element.dataset; let value = element.value; const rule = ruleData.find(r => r.id == id); if (rule) { if (prop === 'keywords') { value = value.split(',').map(k => k.trim()); } rule[prop] = value; populateControls(); // In case a category name was changed } } window.removeRule = function(id) { ruleData = ruleData.filter(r => r.id !== id); renderConfigTable(); populateControls(); } // --- TAB & NAVIGATION --- window.openTab = function(evt, tabName) { const tabContents = document.getElementsByClassName("tab-content"); Array.from(tabContents).forEach(tab => tab.style.display = "none"); const tabButtons = document.getElementsByClassName("tab-btn"); Array.from(tabButtons).forEach(btn => btn.classList.remove("active")); document.getElementById(tabName).style.display = "block"; if (evt) { evt.currentTarget.classList.add("active"); } else { const btnToActivate = Array.from(tabButtons).find(btn => btn.getAttribute('onclick').includes(`'${tabName}'`)); if (btnToActivate) btnToActivate.classList.add("active"); } updateNavButtons(); } window.navigateTabs = function(direction) { const tabs = Array.from(document.querySelectorAll('.tab-btn')); const activeTabIndex = tabs.findIndex(tab => tab.classList.contains('active')); let newIndex = (direction === 'next') ? (activeTabIndex + 1) % tabs.length : (activeTabIndex - 1 + tabs.length) % tabs.length; tabs[newIndex].click(); } function updateNavButtons() { const tabs = Array.from(document.querySelectorAll('.tab-btn')); const activeTabIndex = tabs.findIndex(tab => tab.classList.contains('active')); document.getElementById('prev-btn').style.visibility = activeTabIndex === 0 ? 'hidden' : 'visible'; document.getElementById('next-btn').style.visibility = activeTabIndex === tabs.length - 1 ? 'hidden' : 'visible'; } // --- PDF DOWNLOAD --- if(downloadPdfBtn) { downloadPdfBtn.addEventListener('click', function() { const { jsPDF } = window.jspdf; const contentToDownload = document.getElementById('results-to-download'); if (!contentToDownload || !document.querySelector('.status-banner')) { console.warn("Please generate a compliance check before downloading."); return; } const originalButtonText = downloadPdfBtn.innerHTML; downloadPdfBtn.innerHTML = 'Generating...'; downloadPdfBtn.disabled = true; html2canvas(contentToDownload, { 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) / imgProps.width; pdf.text("HOA Compliance Report", 10, 15); pdf.setFontSize(12); pdf.text(`Project: ${projectDescription.value}`, 10, 25, {maxWidth: 190}); pdf.addImage(imgData, 'PNG', 10, 35, pdfWidth - 20, imgHeight > 0 ? imgHeight - 20 : 0); pdf.save('HOA-Compliance-Report.pdf'); }).catch(err => { console.error("Error generating PDF:", err); }).finally(() => { downloadPdfBtn.innerHTML = originalButtonText; downloadPdfBtn.disabled = false; }); }); } // --- INITIALIZATION --- function initializeTool() { populateControls(); renderConfigTable(); updateNavButtons(); } initializeTool(); });
Scroll to Top