Member Only Content. Member already? Sign-in below if not seeing content below.
Listing Slider Widget Code
Copy and paste the code below into your site.
============================================================
COPY EVERYTHING BETWEEN THE TWO LINES BELOW (not the lines themselves)
============================================================
<!-- Featured Listing Carousel Widget - Free for real estate agents -->
<div id="featured-listings-widget">
<h2 style="text-align:center; margin:20px 0; font-family:Arial,sans-serif;">
Featured Listing
</h2>
<!-- Admin / Upload Section (hidden by default) -->
<div id="adminSection" style="text-align:center; margin:20px 0; display:none;">
<p>Upload images in the order you want them displayed.<br>
Add one at a time or multiple (JPG/PNG).<br>
Portraits show fully top-to-bottom with blank sides.<br>
Max 8 total.</p>
<input type="file" id="listingImages" accept="image/*" multiple style="margin:10px auto; display:block;">
<p id="fileCount" style="font-size:0.9em; color:#666;">No images added yet</p>
<button id="clearBtn" style="margin:10px; padding:8px 16px; background:#f44336; color:white; border:none; border-radius:5px; cursor:pointer;">
Clear All
</button>
<button id="saveLockBtn" style="margin:10px; padding:10px 20px; font-size:1.1em; background:#4CAF50; color:white; border:none; border-radius:5px; cursor:pointer;">
Save & Lock (Hide Upload)
</button>
</div>
<!-- Carousel Container -->
<div class="carousel-container">
<div class="carousel-track" id="carouselTrack">
<!-- Images go here -->
</div>
<!-- Navigation Arrows -->
<button class="carousel-prev" onclick="scrollCarousel(-1)">❮</button>
<button class="carousel-next" onclick="scrollCarousel(1)">❯</button>
</div>
<!-- Dots -->
<div class="carousel-dots" id="carouselDots"></div>
<!-- Admin Trigger -->
<div style="text-align:center; margin-top:30px; font-size:0.85em; color:#888;">
<span id="adminLink" style="color:#0066cc; text-decoration:underline; cursor:pointer;">Admin?</span>
</div>
<div id="passwordPrompt" style="display:none; text-align:center; margin:20px 0; padding:20px; background:#f8f8f8; border-radius:8px;">
<p>Enter admin code:</p>
<input type="password" id="passInput" placeholder="password" style="padding:10px; font-size:1.1em; width:200px;">
<button id="submitPass" style="margin-left:10px; padding:10px 15px;">Unlock</button>
<p id="passError" style="color:red; margin-top:10px; min-height:1.2em;"></p>
</div>
</div>
<style>
#featured-listings-widget {
max-width: 1000px;
margin: 0 auto;
padding: 20px;
font-family: Arial, Helvetica, sans-serif;
}
.carousel-container {
position: relative;
width: 100%;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.15);
background: #000;
overflow: hidden;
}
.carousel-track {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
}
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-slide {
flex: 0 0 100%;
scroll-snap-align: center;
display: flex;
align-items: center;
justify-content: center;
min-height: 250px;
background: #111;
}
.carousel-slide img {
max-width: 100%;
max-height: 70vh;
width: auto;
height: auto;
object-fit: contain;
border-radius: 10px;
background: #f0f0f0;
}
.carousel-prev, .carousel-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.6);
color: white;
border: none;
font-size: 2.8rem;
padding: 12px 18px;
cursor: pointer;
border-radius: 50%;
z-index: 10;
user-select: none;
}
.carousel-prev { left: 15px; }
.carousel-next { right: 15px; }
.carousel-prev:hover, .carousel-next:hover { background: rgba(0,0,0,0.9); }
.carousel-dots { text-align: center; padding: 15px 0; }
.dot {
height: 12px;
width: 12px;
margin: 0 6px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
cursor: pointer;
transition: background-color 0.3s;
}
.dot.active { background-color: #fff; }
</style>
<script>
const STORAGE_KEY = 'featuredListingImages';
const ADMIN_CODE = 'agent';
const MAX_IMAGES = 8;
const track = document.getElementById('carouselTrack');
const dotsContainer = document.getElementById('carouselDots');
const adminSection = document.getElementById('adminSection');
const fileInput = document.getElementById('listingImages');
const fileCount = document.getElementById('fileCount');
const clearBtn = document.getElementById('clearBtn');
const saveBtn = document.getElementById('saveLockBtn');
const adminLink = document.getElementById('adminLink');
const passPrompt = document.getElementById('passwordPrompt');
const passInput = document.getElementById('passInput');
const submitPass = document.getElementById('submitPass');
const passError = document.getElementById('passError');
let currentImages = [];
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
currentImages = JSON.parse(saved);
renderImages(currentImages);
} else {
track.innerHTML = '<div class="carousel-slide" style="color:#aaa; font-size:1.2em; padding:40px; text-align:center;">No featured images yet</div>';
}
function renderImages(urls) {
track.innerHTML = '';
dotsContainer.innerHTML = '';
if (urls.length === 0) {
track.innerHTML = '<div class="carousel-slide" style="color:#aaa; font-size:1.2em; padding:40px; text-align:center;">No featured images yet</div>';
updateCountDisplay();
return;
}
urls.forEach((url, index) => {
const slide = document.createElement('div');
slide.className = 'carousel-slide';
const img = document.createElement('img');
img.src = url;
img.alt = `Featured listing ${index + 1}`;
img.onload = updateActiveDot;
slide.appendChild(img);
track.appendChild(slide);
const dot = document.createElement('span');
dot.className = 'dot';
dot.onclick = () => track.scrollTo({ left: index * track.clientWidth, behavior: 'smooth' });
dotsContainer.appendChild(dot);
});
updateActiveDot();
updateCountDisplay();
}
function updateCountDisplay() {
fileCount.textContent = currentImages.length === 0
? 'No images added yet'
: `${currentImages.length} image${currentImages.length !== 1 ? 's' : ''} added`;
}
function updateActiveDot() {
if (currentImages.length === 0) return;
const idx = Math.round(track.scrollLeft / track.clientWidth);
const dots = dotsContainer.querySelectorAll('.dot');
dots.forEach((d, i) => d.classList.toggle('active', i === idx));
}
adminLink.onclick = function(e) {
e.preventDefault();
passPrompt.style.display = 'block';
adminLink.style.display = 'none';
passInput.focus();
};
submitPass.onclick = function() {
if (passInput.value.trim().toLowerCase() === ADMIN_CODE) {
passPrompt.style.display = 'none';
adminSection.style.display = 'block';
passError.textContent = '';
} else {
passError.textContent = 'Incorrect code.';
passInput.value = '';
}
};
fileInput.addEventListener('change', () => {
const files = fileInput.files;
if (!files.length) return;
if (currentImages.length + files.length > MAX_IMAGES) {
alert(`Max ${MAX_IMAGES} images. Currently: ${currentImages.length}`);
fileInput.value = '';
return;
}
const promises = Array.from(files).map(file => new Promise(r => {
const reader = new FileReader();
reader.onload = () => r(reader.result);
reader.readAsDataURL(file);
}));
Promise.all(promises).then(newUrls => {
currentImages.push(...newUrls);
renderImages(currentImages);
fileInput.value = '';
});
});
clearBtn.onclick = () => {
if (confirm('Clear all images?')) {
currentImages = [];
localStorage.removeItem(STORAGE_KEY);
renderImages([]);
}
};
saveBtn.onclick = () => {
if (!currentImages.length) {
alert('Add at least one image first.');
return;
}
localStorage.setItem(STORAGE_KEY, JSON.stringify(currentImages));
adminSection.style.display = 'none';
alert('Saved & locked! Refresh to see.');
};
function scrollCarousel(dir) {
track.scrollBy({ left: dir * track.clientWidth, behavior: 'smooth' });
}
track.addEventListener('scroll', updateActiveDot);
renderImages(currentImages);
</script>
============================================================
END OF CODE — DO NOT COPY THIS LINE
============================================================
COPY EVERYTHING BETWEEN THE TWO LINES BELOW (not the lines themselves)
============================================================
<!-- Featured Listing Carousel Widget - Free for real estate agents -->
<div id="featured-listings-widget">
<h2 style="text-align:center; margin:20px 0; font-family:Arial,sans-serif;">
Featured Listing
</h2>
<!-- Admin / Upload Section (hidden by default) -->
<div id="adminSection" style="text-align:center; margin:20px 0; display:none;">
<p>Upload images in the order you want them displayed.<br>
Add one at a time or multiple (JPG/PNG).<br>
Portraits show fully top-to-bottom with blank sides.<br>
Max 8 total.</p>
<input type="file" id="listingImages" accept="image/*" multiple style="margin:10px auto; display:block;">
<p id="fileCount" style="font-size:0.9em; color:#666;">No images added yet</p>
<button id="clearBtn" style="margin:10px; padding:8px 16px; background:#f44336; color:white; border:none; border-radius:5px; cursor:pointer;">
Clear All
</button>
<button id="saveLockBtn" style="margin:10px; padding:10px 20px; font-size:1.1em; background:#4CAF50; color:white; border:none; border-radius:5px; cursor:pointer;">
Save & Lock (Hide Upload)
</button>
</div>
<!-- Carousel Container -->
<div class="carousel-container">
<div class="carousel-track" id="carouselTrack">
<!-- Images go here -->
</div>
<!-- Navigation Arrows -->
<button class="carousel-prev" onclick="scrollCarousel(-1)">❮</button>
<button class="carousel-next" onclick="scrollCarousel(1)">❯</button>
</div>
<!-- Dots -->
<div class="carousel-dots" id="carouselDots"></div>
<!-- Admin Trigger -->
<div style="text-align:center; margin-top:30px; font-size:0.85em; color:#888;">
<span id="adminLink" style="color:#0066cc; text-decoration:underline; cursor:pointer;">Admin?</span>
</div>
<div id="passwordPrompt" style="display:none; text-align:center; margin:20px 0; padding:20px; background:#f8f8f8; border-radius:8px;">
<p>Enter admin code:</p>
<input type="password" id="passInput" placeholder="password" style="padding:10px; font-size:1.1em; width:200px;">
<button id="submitPass" style="margin-left:10px; padding:10px 15px;">Unlock</button>
<p id="passError" style="color:red; margin-top:10px; min-height:1.2em;"></p>
</div>
</div>
<style>
#featured-listings-widget {
max-width: 1000px;
margin: 0 auto;
padding: 20px;
font-family: Arial, Helvetica, sans-serif;
}
.carousel-container {
position: relative;
width: 100%;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.15);
background: #000;
overflow: hidden;
}
.carousel-track {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
}
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-slide {
flex: 0 0 100%;
scroll-snap-align: center;
display: flex;
align-items: center;
justify-content: center;
min-height: 250px;
background: #111;
}
.carousel-slide img {
max-width: 100%;
max-height: 70vh;
width: auto;
height: auto;
object-fit: contain;
border-radius: 10px;
background: #f0f0f0;
}
.carousel-prev, .carousel-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0,0,0,0.6);
color: white;
border: none;
font-size: 2.8rem;
padding: 12px 18px;
cursor: pointer;
border-radius: 50%;
z-index: 10;
user-select: none;
}
.carousel-prev { left: 15px; }
.carousel-next { right: 15px; }
.carousel-prev:hover, .carousel-next:hover { background: rgba(0,0,0,0.9); }
.carousel-dots { text-align: center; padding: 15px 0; }
.dot {
height: 12px;
width: 12px;
margin: 0 6px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
cursor: pointer;
transition: background-color 0.3s;
}
.dot.active { background-color: #fff; }
</style>
<script>
const STORAGE_KEY = 'featuredListingImages';
const ADMIN_CODE = 'agent';
const MAX_IMAGES = 8;
const track = document.getElementById('carouselTrack');
const dotsContainer = document.getElementById('carouselDots');
const adminSection = document.getElementById('adminSection');
const fileInput = document.getElementById('listingImages');
const fileCount = document.getElementById('fileCount');
const clearBtn = document.getElementById('clearBtn');
const saveBtn = document.getElementById('saveLockBtn');
const adminLink = document.getElementById('adminLink');
const passPrompt = document.getElementById('passwordPrompt');
const passInput = document.getElementById('passInput');
const submitPass = document.getElementById('submitPass');
const passError = document.getElementById('passError');
let currentImages = [];
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
currentImages = JSON.parse(saved);
renderImages(currentImages);
} else {
track.innerHTML = '<div class="carousel-slide" style="color:#aaa; font-size:1.2em; padding:40px; text-align:center;">No featured images yet</div>';
}
function renderImages(urls) {
track.innerHTML = '';
dotsContainer.innerHTML = '';
if (urls.length === 0) {
track.innerHTML = '<div class="carousel-slide" style="color:#aaa; font-size:1.2em; padding:40px; text-align:center;">No featured images yet</div>';
updateCountDisplay();
return;
}
urls.forEach((url, index) => {
const slide = document.createElement('div');
slide.className = 'carousel-slide';
const img = document.createElement('img');
img.src = url;
img.alt = `Featured listing ${index + 1}`;
img.onload = updateActiveDot;
slide.appendChild(img);
track.appendChild(slide);
const dot = document.createElement('span');
dot.className = 'dot';
dot.onclick = () => track.scrollTo({ left: index * track.clientWidth, behavior: 'smooth' });
dotsContainer.appendChild(dot);
});
updateActiveDot();
updateCountDisplay();
}
function updateCountDisplay() {
fileCount.textContent = currentImages.length === 0
? 'No images added yet'
: `${currentImages.length} image${currentImages.length !== 1 ? 's' : ''} added`;
}
function updateActiveDot() {
if (currentImages.length === 0) return;
const idx = Math.round(track.scrollLeft / track.clientWidth);
const dots = dotsContainer.querySelectorAll('.dot');
dots.forEach((d, i) => d.classList.toggle('active', i === idx));
}
adminLink.onclick = function(e) {
e.preventDefault();
passPrompt.style.display = 'block';
adminLink.style.display = 'none';
passInput.focus();
};
submitPass.onclick = function() {
if (passInput.value.trim().toLowerCase() === ADMIN_CODE) {
passPrompt.style.display = 'none';
adminSection.style.display = 'block';
passError.textContent = '';
} else {
passError.textContent = 'Incorrect code.';
passInput.value = '';
}
};
fileInput.addEventListener('change', () => {
const files = fileInput.files;
if (!files.length) return;
if (currentImages.length + files.length > MAX_IMAGES) {
alert(`Max ${MAX_IMAGES} images. Currently: ${currentImages.length}`);
fileInput.value = '';
return;
}
const promises = Array.from(files).map(file => new Promise(r => {
const reader = new FileReader();
reader.onload = () => r(reader.result);
reader.readAsDataURL(file);
}));
Promise.all(promises).then(newUrls => {
currentImages.push(...newUrls);
renderImages(currentImages);
fileInput.value = '';
});
});
clearBtn.onclick = () => {
if (confirm('Clear all images?')) {
currentImages = [];
localStorage.removeItem(STORAGE_KEY);
renderImages([]);
}
};
saveBtn.onclick = () => {
if (!currentImages.length) {
alert('Add at least one image first.');
return;
}
localStorage.setItem(STORAGE_KEY, JSON.stringify(currentImages));
adminSection.style.display = 'none';
alert('Saved & locked! Refresh to see.');
};
function scrollCarousel(dir) {
track.scrollBy({ left: dir * track.clientWidth, behavior: 'smooth' });
}
track.addEventListener('scroll', updateActiveDot);
renderImages(currentImages);
</script>
============================================================
END OF CODE — DO NOT COPY THIS LINE
============================================================