<script>
document.addEventListener('DOMContentLoaded', function() {
const subString = '/sitemap';
const getURL = window.location.href;
const mapSearchInputContainer = document.querySelector('#mapSearchInputContainer');
const containerHouses = document.getElementById('sitemaphouse-image-container');
if (getURL.includes(subString)) {
// Array of image URLs
const imageArray = [
'https://images.squarespace-cdn.com/content/v1/6654b2fee26f292de13f1a9d/09531fcb-25ed-4aaa-86cd-4ca1d685f938/House19.png',
'https://images.squarespace-cdn.com/content/v1/6654b2fee26f292de13f1a9d/828970b0-b68b-4201-94b4-1dfbc5e979cd/House20.png',
'https://images.squarespace-cdn.com/content/v1/6654b2fee26f292de13f1a9d/604324af-0d6b-4f16-8dc7-c7e77d8e343c/House21.png'
];
//embed the map
const sitemapPlaceTextBlock = document.getElementById('block-yui_3_17_2_1_1725267087091_56500');
const sitemapPlaceText = sitemapPlaceTextBlock.querySelector('p');
sitemapPlaceText.textContent = '';
const containerMain = document.createElement('div');
containerMain.id = 'sitemap-container-main';
const container = document.createElement('div');
container.id = 'sitemap-container';
containerMain.appendChild(container);
sitemapPlaceTextBlock.appendChild(containerMain);
//embed houses
const housesPlaceTextBlock = document.getElementById('block-69cee297babf88af4600');
const housesPlaceText = housesPlaceTextBlock.querySelector('p');
housesPlaceText.textContent = '';
housesPlaceTextBlock.appendChild(containerHouses);
//filter and structuring options
const sitemapUrl = 'https://www.polivantage.com/sitemap.xml';
const excludedPatterns = ['/404', '/shop/p/', '/developmentlog', '/sitemap'];
const categoryPatterns = {
'Main:': ['/history', '/home', '/services', '/contact', '/legal', '/devlog', '/art'],
'Shop:': ['/shop'],
'Art:': []
};
const categoryOrder = ['Main:', 'Shop:', 'Art:'];
//to highlight links by house
function highlightLink(imageLink) {
const textLinks = container.querySelectorAll('a');
textLinks.forEach(textLink => {
if (textLink.href === imageLink) {
textLink.style.color = '#ea4b1a';
} else {
textLink.style.color = '';
}
});
}
//to fetch and format the title from the JSON endpoint
async function getDisplayTextFromJson(url) {
try {
const response = await fetch(`${url}?format=json-pretty`);
const jsonData = await response.json();
return jsonData.collection.title || url;
} catch (error) {
console.error('Error fetching JSON data:', error);
return url; // Fallback to URL if there is an error
}
}
//retrieve the map and filter it
fetch(sitemapUrl)
.then(response => response.text())
.then(str => new window.DOMParser().parseFromString(str, "text/xml"))
.then(async data => {
const urls = data.querySelectorAll('url');
let imageIndex = 0;
const categories = {};
const houseImageMapping = [];
//format the display text using jsons
const titlePromises = Array.from(urls).map(async url => {
const loc = url.querySelector('loc').textContent;
let exclude = false;
excludedPatterns.forEach(pattern => {
if (loc.includes(pattern)) {
exclude = true;
}
});
if (exclude) return;
let displayText;
//shop category will not use json to format text
if (categoryPatterns['Shop:'].some(pattern => loc.includes(pattern))) {
displayText = loc.replace('https://www.polivantage.com/', '');
displayText = displayText.replace('developmentlog/', '');
displayText = displayText.replace('shop/', '');
displayText = displayText.charAt(0).toUpperCase() + displayText.slice(1);
} else {
displayText = await getDisplayTextFromJson(loc);
}
let category = 'Art:';
for (const [cat, patterns] of Object.entries(categoryPatterns)) {
if (patterns.some(pattern => loc.includes(pattern))) {
category = cat;
break;
}
}
if (!categories[category]) {
categories[category] = [];
}
categories[category].push({ href: loc, text: displayText });
//create houses
const imageWrapper = document.createElement('div');
imageWrapper.className = 'sitemaphouse-image-wrapper';
const img = document.createElement('img');
img.src = imageArray[imageIndex % imageArray.length];
img.alt = displayText;
houseImageMapping.push({ link: loc, imgWrapper: imageWrapper });
imageWrapper.addEventListener('click', function() {
window.location.href = loc;
});
imageWrapper.addEventListener('mouseover', () => highlightLink(loc));
imageWrapper.addEventListener('mouseout', () => highlightLink(''));
imageWrapper.appendChild(img);
img.classList.add('loaded');
const randomScale = 1 + Math.random() * 0.3;
imageWrapper.style.minWidth = `${randomScale * 150}px`;
imageIndex++;
});
//create html structure
await Promise.all(titlePromises);
let htmlContent = '<div class="category-main-container">';
categoryOrder.forEach(category => {
if (categories[category]) {
const categoryClass = 'category-' + category.replace(/:/g, '').toLowerCase();
htmlContent += `<div class="category-container ${categoryClass}">
<h4>${category}</h4><ul>`;
categories[category].forEach(link => {
htmlContent += `<li><a href="${link.href}">${link.text}</a></li>`;
const house = houseImageMapping.find(h => h.link === link.href);
if (house) {
containerHouses.appendChild(house.imgWrapper);
}
});
htmlContent += `</ul></div>`;
}
});
htmlContent += '</div>';
container.innerHTML = htmlContent;
container.style.minWidth = `${container.offsetWidth}px`;
})
.catch(error => console.error('Error fetching sitemap:', error));
//embed the search
const mapSearchPlaceTextBlock = document.getElementById('block-79e0b6b6e5aa365774d8');
const mapSearchPlaceText = mapSearchPlaceTextBlock.querySelector('p');
mapSearchPlaceText.textContent = '';
mapSearchPlaceTextBlock.appendChild(mapSearchInputContainer);
//handle search
const mapSearchInput = document.querySelector('#mapSearchInput');
const debounceDelay = 700;
let debounceTimeout;
mapSearchInput.addEventListener('input', function() {
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(() => {
const titles = container.querySelectorAll('a');
const query = this.value.toLowerCase();
titles.forEach(title => {
const titleText = title.textContent.toLowerCase();
const listItem = title.closest('li');
if (titleText.includes(query)) {
listItem.style.display = '';
} else {
listItem.style.display = 'none';
}
});
// Filter house images
const houseImages = containerHouses.querySelectorAll('img');
houseImages.forEach(img => {
const imgAlt = img.alt.toLowerCase();
const wrapper = img.parentElement;
wrapper.style.display = imgAlt.includes(query) ? '' : 'none';
});
//hide empty categories
const allCategories = container.querySelectorAll('h4');
allCategories.forEach(category => {
const categoryList = category.nextElementSibling;
const visibleItems = categoryList.querySelectorAll('li:not([style*="display: none"])');
if (visibleItems.length === 0) {
category.style.display = 'none';
categoryList.style.display = 'none';
} else {
category.style.display = '';
categoryList.style.display = '';
}
});
}, debounceDelay);
});
//clear input if click outside of search depending on input value
var hasText = false;
function checkInput() {
hasText = mapSearchInput.value.trim() !== '';
}
document.addEventListener('click', function(event) {
checkInput();
if (event.target !== mapSearchInput && hasText == false) {
mapSearchInput.classList.remove('texted');
} else {
mapSearchInput.classList.add('texted');
}
});
//houses scroll behavior
if (!containerHouses) return;
let scrollInterval;
const maxScrollSpeed = 120; // Maximum scroll speed (pixels per frame)
const buffer = 500; // Distance from the edge where scroll starts
const scrollCheckInterval = 20; // Interval to check scroll speed
let isScrolling = false;
function calculateScrollSpeed(mouseX, containerWidth) {
const scrollArea = containerWidth / 2 - buffer;
const distanceFromLeftEdge = mouseX - buffer;
const distanceFromRightEdge = containerWidth - mouseX - buffer;
let scrollSpeed = 0;
if (distanceFromLeftEdge < 0) {
scrollSpeed = -Math.min(maxScrollSpeed, (-distanceFromLeftEdge / scrollArea) * maxScrollSpeed);
} else if (distanceFromRightEdge < 0) {
scrollSpeed = Math.min(maxScrollSpeed, (-distanceFromRightEdge / scrollArea) * maxScrollSpeed);
}
return scrollSpeed;
}
function startScrolling() {
if (isScrolling) return; // Prevent multiple intervals from being set
isScrolling = true;
scrollInterval = setInterval(function () {
const containerRect = containerHouses.getBoundingClientRect();
const mouseX = window.mouseX - containerRect.left;
const scrollSpeed = calculateScrollSpeed(mouseX, containerRect.width);
if (scrollSpeed !== 0) {
containerHouses.scrollLeft += scrollSpeed;
} else {
stopScrolling();
}
}, scrollCheckInterval);
}
function stopScrolling() {
clearInterval(scrollInterval);
isScrolling = false;
}
function updateMousePosition(event) {
window.mouseX = event.clientX;
}
containerHouses.addEventListener('mousemove', function (event) {
updateMousePosition(event);
if (!isScrolling) {
startScrolling();
}
});
containerHouses.addEventListener('mouseenter', function (event) {
updateMousePosition(event);
startScrolling();
});
containerHouses.addEventListener('mouseleave', function () {
stopScrolling();
});
//exit
} else {
mapSearchInputContainer.remove();
containerHouses.remove();
}
});
</script>