Available Rental Properties
Find rental properties in Jefferson and Shelby County, AL through rental listings built to make the search easier from the first click. Across Jefferson County and Shelby County, Lease Birmingham gives renters a cleaner path through available homes, current details, and the first hard questions that decide whether a showing is worth the time. Start with the listings, choose the home that fits, and move before the good one is gone.
Search
Filter
// Clear search and filters document.getElementById("clear-search").addEventListener("click", function() { document.getElementById("search-input").value = ""; document.getElementById("city-filter").value = ""; document.getElementById("bedrooms-filter").value = ""; document.getElementById("bathrooms-filter").value = ""; document.querySelectorAll(".rentvine-card").forEach(function(card) { card.style.display = "block"; }); });
// Filter functionality document.querySelectorAll("#city-filter, #bedrooms-filter, #bathrooms-filter").forEach(function(select) { select.addEventListener("change", function() { var city = document.getElementById("city-filter").value.toLowerCase(); var bedrooms = document.getElementById("bedrooms-filter").value.toLowerCase(); var bathrooms = document.getElementById("bathrooms-filter").value.toLowerCase();
var cards = document.querySelectorAll(".rentvine-card"); cards.forEach(function(card) { var cardCity = card.getAttribute("data-city").toLowerCase(); var cardBedrooms = card.getAttribute("data-beds").toLowerCase(); var cardBathrooms = card.getAttribute("data-baths").toLowerCase();
var showCard = true; if (city && cardCity !== city) showCard = false; if (bedrooms && cardBedrooms !== bedrooms) showCard = false; if (bathrooms && cardBathrooms !== bathrooms) showCard = false;
if (showCard) { card.style.display = "block"; } else { card.style.display = "none"; } }); }); });
// Search functionality document.getElementById("search-input").addEventListener("input", function() { var searchText = this.value.toLowerCase(); var cards = document.querySelectorAll(".rentvine-card"); cards.forEach(function(card) { var address = card.querySelector(".rv-address").textContent.toLowerCase(); var city = card.querySelector(".rv-address").textContent.toLowerCase(); var zip = card.querySelector(".rv-address").textContent.toLowerCase(); if (address.includes(searchText) || city.includes(searchText) || zip.includes(searchText)) { card.style.display = "block"; } else { card.style.display = "none"; } }); });
let map;
function initializeMap(lat, lng) { if (map) { map.remove(); map = null; } const latNum = Number(lat), lngNum = Number(lng); if (!Number.isFinite(latNum) || !Number.isFinite(lngNum)) return; map = L.map("lightbox-map").setView([latNum, lngNum], 15); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: "© OpenStreetMap contributors" }).addTo(map); L.marker([latNum, lngNum]).addTo(map).bindPopup("Property Location"); setTimeout(() => map.invalidateSize(), 300); }
// Build slider like the CodePen: slides row, overlay arrows, dots, translateX animation function initRvSlider(root, images, options) { const cfg = Object.assign({ autoplay: true, interval: 4000, loop: true }, options || {}); const track = root.querySelector(".rv-slides"); const dotsWrap = root.querySelector(".rv-dots"); const prevBtn = root.querySelector(".rv-prev"); const nextBtn = root.querySelector(".rv-next");
const n = Math.max(1, images.length); track.innerHTML = images.map((src, i) => `
` ).join("");
dotsWrap.innerHTML = images.map((_, i) => `` ).join("");
let index = 0; let timer = null; let isHovered = false;
const slides = Array.from(track.children); const dots = Array.from(dotsWrap.children);
function go(i) { if (!cfg.loop) { i = Math.max(0, Math.min(n-1, i)); } else { i = (i + n) % n; } index = i; const offset = -(index * 100); track.style.transform = "translateX(" + offset + "%)"; dots.forEach((d, di) => d.classList.toggle("is-active", di === index)); }
function next() { go(index + 1); } function prev() { go(index - 1); }
dots.forEach((d, di) => d.addEventListener("click", () => { go(di); }));
prevBtn.addEventListener("click", prev); nextBtn.addEventListener("click", next);
// autoplay function start() { if (!cfg.autoplay || timer) return; timer = setInterval(() => { if (!isHovered) next(); }, cfg.interval); } function stop() { if (timer) { clearInterval(timer); timer = null; } }
root.addEventListener("mouseenter", () => { isHovered = true; }); root.addEventListener("mouseleave", () => { isHovered = false; });
// keyboard root.setAttribute("tabindex", "0"); root.addEventListener("keydown", (e) => { if (e.key === "ArrowLeft") prev(); if (e.key === "ArrowRight") next(); });
// touch swipe let startX = 0, dx = 0, dragging = false; root.addEventListener("touchstart", (e) => { startX = e.touches[0].clientX; dx = 0; dragging = true; stop(); }, {passive:true}); root.addEventListener("touchmove", (e) => { if (!dragging) return; dx = e.touches[0].clientX - startX; }, {passive:true}); root.addEventListener("touchend", () => { if (!dragging) return; dragging = false; if (Math.abs(dx) > 40) { (dx < 0 ? next() : prev()); } start(); }); go(0); start(); return { go, next, prev, start, stop, destroy: () => { stop(); } }; }
// Lightbox: populate details, build slider, init map document.addEventListener("click", function (e) { const btn = e.target.closest(".rv-details-button"); if (!btn) return;
const card = btn.closest(".rentvine-card"); let images = []; try { const raw = card.getAttribute("data-images") || "[]"; JSON.parse(raw).forEach(src => { if (src) images.push(src); }); } catch (err) {} if (!images.length) images = ["https://placehold.co/800x500?text=No+Image"];
const lat = card.getAttribute("data-latitude"); const lng = card.getAttribute("data-longitude"); initializeMap(lat, lng);
const address = card.getAttribute("data-address") || ""; const beds = card.getAttribute("data-beds") || "N/A"; const baths = card.getAttribute("data-baths") || "N/A"; const title = card.getAttribute("data-title") || ""; const yearBuilt = card.getAttribute("data-year-built") || "N/A"; const unitSize = card.getAttribute("data-unit-size") || "N/A"; const rentText = (card.querySelector(".rv-price")?.textContent || "Contact for Rent");
document.getElementById("lb-title").textContent = title;
document.getElementById("lb-address").textContent = address;
document.getElementById("lb-rent").textContent = rentText;
document.getElementById("lb-unit").innerHTML = "Unit size:
" + unitSize + " sq. ft.";
document.getElementById("lb-beds").innerHTML = "Bedrooms:
" + beds + "";
document.getElementById("lb-baths").innerHTML = "Bathrooms:
" + baths + "";
document.getElementById("lb-year").innerHTML = "Year Built:
" + yearBuilt + "";
const sliderRoot = document.getElementById("lightbox-slider"); // Clear previous slider sliderRoot.querySelector(".rv-slides").innerHTML = ""; sliderRoot.querySelector(".rv-dots").innerHTML = ""; const sliderApi = initRvSlider(sliderRoot, images, { autoplay: true, interval: 4500, loop: true });
// open document.getElementById("lightbox").style.display = "block"; });
// Close lightbox document.getElementById("close-lightbox").addEventListener("click", function () { document.getElementById("lightbox").style.display = "none"; });
document.addEventListener("keydown", function(e){ if (e.key === "Escape") document.getElementById("close-lightbox").click(); });