function rzInitCalcWidget() { var widget = { selected: null, nudges: { 27214: [0, -70], 27284: [-10, -30], 27235: [-40, 10], 27260: [15, 40], 27377: [0, 50], 27409: [-50, 145], }, data: { 27401: {"zip":"27401","rooms":["1122","1177","1287","1650","1892","2098"]}, 27403: {"zip":"27403","rooms":["1232","1287","1408","1804","2079","2295"]}, 27405: {"zip":"27405","rooms":["1100","1150","1260","1610","1860","2054"]}, 27406: {"zip":"27406","rooms":["1190","1250","1370","1750","2020","2233"]}, 27407: {"zip":"27407","rooms":["1313","1376","1512","1932","2226","2465"]}, 27408: {"zip":"27408","rooms":["1220","1280","1400","1790","2060","2060"]}, 27409: {"zip":"27409","rooms":["1292","1355","1481","1901","2184","2413"]}, 27410: {"zip":"27410","rooms":["1520","1600","1750","2240","2580","2853"]}, 27455: {"zip":"27455","rooms":["1310","1370","1500","1920","2210","2445"]}, 27495: {"zip":"27495","rooms":["1190","1250","1370","1750","2020","2233"]}, 27249: {"zip":"27249","rooms":["1116","1219","1346","1714","1978","2193"]}, 27282: {"zip":"27282","rooms":["1450","1520","1670","2140","2460","2722"]}, 27284: {"zip":"27284","rooms":["1265","1369","1553","2024","2392","2531"]}, 27313: {"zip":"27313","rooms":["1067","1111","1221","1562","1804","1990"]}, 27357: {"zip":"27357","rooms":["1020","1092","1296","1644","1872","2112"]}, 27358: {"zip":"27358","rooms":["1240","1310","1470","1870","2150","2396"]}, 27301: {"zip":"27301","rooms":["1740","1820","2000","2560","2950","3260"]}, 27310: {"zip":"27310","rooms":["1369","1461","1633","2105","2461","2662"]}, 27377: {"zip":"27377","rooms":["1441","1507","1650","2112","2431","2690"]}, 27214: {"zip":"27214","rooms":["1210","1270","1410","1800","2080","2298"]}, 27235: {"zip":"27235","rooms":[0,0,0,0,0,0]}, 27260: {"zip":"27260","rooms":["1133","1188","1298","1661","1914","2116"]}, 27262: {"zip":"27262","rooms":["1187","1239","1365","1754","2027","2225"]}, 27263: {"zip":"27263","rooms":["1122","1177","1287","1650","1892","2098"]}, 27265: {"zip":"27265","rooms":["1357","1428","1561","2020","2346","2544"]}, }, }; var insertTarget = document.querySelector("#rz-calc-widget"); if (!insertTarget) { console.error(`Revize.rzInitCalcWidget: Script element is missing ID #rz-calc-widget.`); return; } if (insertTarget.dataset['target']) { var tryInsertTarget = document.querySelector(insertTarget.dataset['target']); if (tryInsertTarget) { insertTarget = tryInsertTarget; } } function buildSchema() { var schema = document.createElement("div"); schema.innerHTML = `

Determine Affordability

`; return schema.children[0]; } function appendStyles() { var styles = document.createElement("style"); styles.innerHTML = ` .tabs-wrapper{ width:100%; max-height:100vh; } .content-wrapper{ display:grid; grid-template-columns:100% 100%; grid-template-rows:90vh; overflow:hidden; } .tabs-wrapper .tab-content{transform:translate(0, 0);transition:transform 0.5s ease} .tabs-wrapper.tab-1>header>ul>li:nth-of-type(1)>button{background:#1F408D} .tabs-wrapper.tab-2>header>ul>li:nth-of-type(2)>button{background:#1F408D} .tabs-wrapper.tab-1 .tab-content{transform:translate(0%, 0)} .tabs-wrapper.tab-2 .tab-content{transform:translate(-100%, 0)} .tabs-wrapper.tab-3 .tab-content{transform:translate(-200%, 0)} .tabs-wrapper>header{ display:flex; justify-content:center; } .tabs-wrapper>header>ul::before{ content:''; height:10px; background:radial-gradient(); position:absolute; left:0; right:0; } .tabs-wrapper>header>ul{ position:relative; list-style:none; margin:0; padding:0; display:flex; justify-content:center; align-items:center; gap:0 15px; } .tabs-wrapper>header>ul>li{position:relative} .tabs-wrapper>header>ul>li>button{ background:#CCC; color:#FFF; font-weight:bold; padding:10px 15px; border:0; border-radius:10px; } svg{height:100%;width:100%} svg path{cursor:pointer;fill:transparent} .zip-map { path { transition:transform 0.3s ease; transform-box:fill-box; transform-origin:50% 50%; &:hover, &:focus { transform:scale(1.02); } } text { pointer-events:none; filter:drop-shadow(1px 1px 1px rgba(0, 0, 0, 0.5)); text-anchor:middle; font-size:clamp(20px, 4vw, 30px); } } #zip-select-wrap{ position:absolute; top:15px; left:15px; ul { background:rgba(255, 255, 255, 0.15); border:1px solid #51689f; box-shadow:2px 2px 5px 0 rgba(0, 0, 0, 0.15); list-style:none; padding:5px; margin:0; text-align:center; display:grid; gap:5px; grid-template-columns:1fr 1fr 1fr 1fr 1fr; } button { background:#51689f; color:#fff; border-radius:0; border:0; } } #zip-map-form table { table-layout:fixed; th, td { width:50%; text-align:left; } } #zip-map-form [data-type='affordability'] { i { display:inline-block; width:19px; text-align:center; border-radius:2px; } } :root { --spacing:0.25rem; --font-sans:"Questrial", sans-serif; --bg-color:#e9e9e9; --color:#1B1B18; } /* Helpers */ .p-0{padding:0} .p-1{padding:var(--spacing)} .p-2{padding:calc(var(--spacing) * 2)} .p-3{padding:calc(var(--spacing) * 3)} .p-4{padding:calc(var(--spacing) * 4)} .py-0{padding-block:0} .py-1{padding-block:var(--spacing)} .py-2{padding-block:calc(var(--spacing) * 2)} .py-3{padding-block:calc(var(--spacing) * 3)} .py-4{padding-block:calc(var(--spacing) * 4)} .px-0{padding-inline:0} .px-1{padding-inline:var(--spacing)} .px-2{padding-inline:calc(var(--spacing) * 2)} .px-3{padding-inline:calc(var(--spacing) * 3)} .px-4{padding-inline:calc(var(--spacing) * 4)} .m-0{margin:0} .m-1{margin:var(--spacing)} .m-2{margin:calc(var(--spacing) * 2)} .m-3{margin:calc(var(--spacing) * 3)} .m-4{margin:calc(var(--spacing) * 4)} .my-0{margin-block:0} .my-1{margin-block:var(--spacing)} .my-2{margin-block:calc(var(--spacing) * 2)} .my-3{margin-block:calc(var(--spacing) * 3)} .my-4{margin-block:calc(var(--spacing) * 4)} .mx-0{margin-inline:0} .mx-1{margin-inline:var(--spacing)} .mx-2{margin-inline:calc(var(--spacing) * 2)} .mx-3{margin-inline:calc(var(--spacing) * 3)} .mx-4{margin-inline:calc(var(--spacing) * 4)} .gap-1{gap:var(--spacing)} .gap-2{gap:calc(var(--spacing) * 2)} .gap-3{gap:calc(var(--spacing) * 3)} .gap-4{gap:calc(var(--spacing) * 4)} .text-light{color:#1b1b18} .text-dark{color:#EDEDEC} .flex{display:flex!important} .grid{display:grid!important} .none{display:none!important} .flex-col{flex-direction:column} .flex-1\\/2{flex:1 1 50%} .flex-1{flex:1 1 100%} .border{border:1px solid #CCC} .rounded{border-radius:5px} .w-full{width:100%} .align-center{align-items:center} .justify-center{justify-content:center} .danger{background-color:rgba(255, 0, 0, 0.5)} .success{background-color:rgba(0, 255, 0, 0.5)} .bg-danger{background-color:rgba(255, 0, 0, 0.2)} .bg-black{background-color:#000} .text-center{text-align:center} .text-right{text-align:right} i.icon{display:inline-block;height:1rem;width:1rem;text-align:center;border-radius:50%;background:var(--color);color:var(--bg-color);font-weight:700} #zip-code-27401{ fill:#43fe7b } #zip-code-27403{ fill:#52fffc } #zip-code-27405{ fill:#c8fe86 } #zip-code-27406{ fill:#a280ff } #zip-code-27407{ fill:#90f1fe } #zip-code-27408{ fill:#fedd67 } #zip-code-27409{ fill:#94cbff } #zip-code-27410{ fill:#ff52a5 } #zip-code-27455{ fill:#86fe9a } #zip-code-27495{ fill:#ffd6d6 } #zip-code-27249{ fill:#a3ff47 } #zip-code-27282{ fill:#fead62 } #zip-code-27284{ fill:#ffffff } #zip-code-27313{ fill:#c7fffe } #zip-code-27357{ fill:#c8dcdf } #zip-code-27358{ fill:#ffe95c } #zip-code-27301{ fill:#a59eff } #zip-code-27310{ fill:#fed69f } #zip-code-27377{ fill:#ff7a7a } #zip-code-27214{ fill:#e4ccaa } #zip-code-27235{ fill:#ffffff } #zip-code-27260{ fill:#8fff91 } #zip-code-27262{ fill:#c3dffe } #zip-code-27263{ fill:#ffc7c7 } #zip-code-27265{ fill:#ceff85 } `; document.head.append(styles); } function calculateZipMap(schema) { var calcFields = { agi: null, rent: null, utility: null, bedrooms: null, }; schema.querySelectorAll("#zip-map-form input[name], #zip-map-form select[name]").forEach(function(inp) { if (calcFields.hasOwnProperty(inp.name)) { var val = parseFloat(inp.value); if (isNaN(val)) { return; } calcFields[inp.name] = val; } }); function passedFormula(calcFields, threshold) { if (Object.values(calcFields).filter(v => { if (v === undefined || v === null || v === '') { return true } }).length) { return null; }; var A2 = calcFields.agi; var C2 = calcFields.rent; var D2 = calcFields.utility; var grossRent = C2 + D2; var maxA = (A2 / 12 * 0.40); var ttp = (A2 / 12 * 0.30); var safmrDiff = Math.max(0, grossRent - threshold); return (ttp + safmrDiff <= maxA); } schema.querySelectorAll("#zip-map-baselines td[data-type='affordability']").forEach(function(cell, i) { if (calcFields.bedrooms != -1 && calcFields.bedrooms != i) { cell.parentElement.style.display = "none"; } else { cell.parentElement.style.display = ""; } var threshold = parseFloat(widget.selected.rooms[i]); var allowed = passedFormula(calcFields, threshold); if (allowed === true) { cell.innerHTML = `✓`; } else if (allowed === false) { cell.innerHTML = `✕`; } else if (allowed === null) { cell.innerHTML = `?`; } }); } function selectZip(schema, zip) { if (!widget.data.hasOwnProperty(zip)) { return; } widget.selected = widget.data[zip]; schema.querySelectorAll("#zip-map-baselines td[data-type='cost']").forEach(function(el, i) { if (widget.selected.rooms.length > i) { el.innerText = "$" + widget.selected.rooms[i]; } }); calculateZipMap(schema); schema.querySelector("#zip-select-menu").ariaHidden = "false"; schema.querySelector("#zip-select-toggle").dispatchEvent(new Event('click')); schema.querySelectorAll("header li button").forEach(function(el, i) { if (i === 1) { el.click(); } }); Promise.all( Array.from(schema.querySelectorAll(".tab-content")).map( function(el) { return new Promise(function(res, rej) { el.addEventListener('transitionend', function() { res(); }); }); } ) ).then(() => { var curSlide = parseInt(schema.className.match(/tab-(\d+?)/)?.at(1) ?? 0); schema.querySelectorAll(".tab-content").forEach(function(tab, i) { tab.querySelectorAll("input, path, button").forEach(function(focusable) { if (i === curSlide - 1) { focusable.tabIndex = 0; } else { focusable.tabIndex = -1; } }); }); }); } function bindTabs(schema) { schema.querySelectorAll("button.tab").forEach(function(but, i) { const BUT = but; const I = i; BUT.addEventListener('click', function() { schema.className = schema.className.replace(/(\s)?tab-[0-9]+/, ""); schema.classList.add("tab-" + (I + 1)); }); }); } function tagSVGs(schema) { schema.querySelectorAll("svg").forEach(function(el) { var minX = Infinity; var minY = Infinity; var maxX = -Infinity; var maxY = -Infinity; el.querySelectorAll("path").forEach(function(path) { path.tabIndex = 0; var coordData = path.getAttribute("d"); var lMinX = Infinity; var lMinY = Infinity; var lMaxX = -Infinity; var lMaxY = -Infinity; var bounds = path.getBBox(); lMinX = bounds.x; lMinY = bounds.y; lMaxX = bounds.x + bounds.width; lMaxY = bounds.y + bounds.height; if (lMinX < minX) { minX = lMinX; } if (lMaxX > maxX) { maxX = lMaxX; } if (lMinY < minY) { minY = lMinY; } if (lMaxY > maxY) { maxY = lMaxY; } const ZIP = path.id.replaceAll(/[^0-9]/g, ""); if (path.id.indexOf("zip-code-") === 0 && ZIP.length === 5) { path.addEventListener('click', function() { selectZip(schema, ZIP); }); path.addEventListener('keydown', function(e) { if (e.key === " " || e.key === "Enter") { this.dispatchEvent(new Event('click')); } }); path.addEventListener('mouseenter', function() { if (this.nextElementSibling !== null) { this.parentElement.append(this); } }); var text = document.createElementNS("http://www.w3.org/2000/svg", "text"); text.textContent = ZIP; var nudgeX = 0 var nudgeY = 0; if (widget.nudges.hasOwnProperty(ZIP)) { nudgeX = widget.nudges[ZIP][0] ?? 0; nudgeY = widget.nudges[ZIP][1] ?? 0; } text.setAttribute("x", (lMaxX - lMinX) / 2 + lMinX + nudgeX); text.setAttribute("y", (lMaxY - lMinY) / 2 + lMinY + nudgeY); el.append(text); } }); }); } function bindHandlers(schema) { schema.querySelector("#zip-select-toggle").addEventListener('click', function() { var menu = schema.querySelector("#zip-select-menu"); menu.ariaHidden = (menu.ariaHidden === "true" ? "false" : "true"); menu.style.display = (menu.ariaHidden === "true" ? 'none' : ''); }); schema.querySelectorAll("#zip-map-form input").forEach(function(inp) { inp.addEventListener('input', function() { calculateZipMap(schema); }); }); schema.querySelectorAll("#zip-map-form select").forEach(function(inp) { inp.addEventListener('change', function() { calculateZipMap(schema); }); }); schema.querySelectorAll("#zip-select-menu button[data-zip]").forEach(function(but) { const ZIP = but.dataset['zip']; but.addEventListener('click', function() { selectZip(schema, ZIP); }) }); } var schema = buildSchema(); bindTabs(schema); bindHandlers(schema); appendStyles(); insertTarget.after(schema); tagSVGs(schema); } rzInitCalcWidget();