Files
RateMyBrick/script.js
T
Mathieu Moran 91bcaea90a fixed match modal centering on iphone
prevented body scroll when modal shows

viewport units and mobile responsive fixes
overflow hidden on body/html when match popup active
mobile media queries for smaller screens

terry davis would be proud of this viewport handling
2025-12-28 04:47:06 -05:00

364 lines
11 KiB
JavaScript

// Brick data - loaded from Pexels API downloads
const bricks = [
{
id: 1,
name: "Old Brick Wall",
image: "images/brick_01.jpg",
description: "A moody close-up of an old brick wall with character.",
color: "Brown",
texture: "Weathered"
},
{
id: 2,
name: "Dark Brick Wall",
image: "images/brick_02.jpg",
description: "Close-up texture of a dark, rough brick wall.",
color: "Dark Brown",
texture: "Rough"
},
{
id: 3,
name: "White Brick Wall",
image: "images/brick_03.jpg",
description: "A minimalist white brick wall casting shadows.",
color: "White",
texture: "Smooth"
},
{
id: 4,
name: "Red Brick Building",
image: "images/brick_04.jpg",
description: "Red-brick modern building against a vibrant blue sky.",
color: "Red",
texture: "Modern"
},
{
id: 5,
name: "Weathered Red Brick",
image: "images/brick_05.jpg",
description: "A detailed view of a weathered red brick wall.",
color: "Red",
texture: "Weathered"
},
{
id: 6,
name: "Ancient Brick Archway",
image: "images/brick_06.jpg",
description: "The timeless beauty of an ancient brick archway.",
color: "Brown",
texture: "Aged"
},
{
id: 7,
name: "Vintage Brick Door",
image: "images/brick_07.jpg",
description: "A vintage wooden door set in historic brickwork.",
color: "Brown",
texture: "Vintage"
},
{
id: 8,
name: "Brick Archway",
image: "images/brick_08.jpg",
description: "Captivating brick archway showcasing architectural beauty.",
color: "Brown",
texture: "Textured"
},
{
id: 9,
name: "Ancient Stone Masonry",
image: "images/brick_09.jpg",
description: "Explore the timeless beauty of ancient stone masonry with a view through a historic window in ruins.",
color: "Brown",
texture: "Ancient"
},
{
id: 10,
name: "Pink Brick Wall",
image: "images/brick_10.jpg",
description: "Light pink textured brick wall corner perfect for backgrounds and design.",
color: "Pink",
texture: "Textured"
},
{
id: 11,
name: "Urban Brick Alley",
image: "images/brick_11.jpg",
description: "Explore the character of a narrow urban alley lined with rustic brick walls and faded graffiti.",
color: "Brown",
texture: "Rustic"
},
{
id: 12,
name: "Red Brick Wall",
image: "images/brick_12.jpg",
description: "High-resolution image of a red brick wall with white mortar lines, perfect for backgrounds.",
color: "Red",
texture: "Classic"
},
{
id: 13,
name: "Aged Brick Window",
image: "images/brick_13.jpg",
description: "A cat peeks through a wooden window of an aged building, adding charm.",
color: "Brown",
texture: "Aged"
},
{
id: 14,
name: "Roman Stone Arch",
image: "images/brick_14.jpg",
description: "Detailed view of an ancient Roman stone arch with ornate decorative carvings.",
color: "Brown",
texture: "Ornate"
},
{
id: 15,
name: "Cozy Brick Fireplace",
image: "images/brick_15.jpg",
description: "Cozy winter fireplace with brickwork showcasing warm textures.",
color: "Brown",
texture: "Cozy"
},
{
id: 16,
name: "Classic Brick Doorway",
image: "images/brick_16.jpg",
description: "A classic wooden door set in an ancient stone wall with a decorative flower wreath.",
color: "Brown",
texture: "Classic"
}
];
let currentIndex = 0;
let likedCount = 0;
let startX = 0;
let startY = 0;
let currentX = 0;
let currentY = 0;
let isDragging = false;
const card = document.getElementById('currentCard');
const brickImage = document.getElementById('brickImage');
const brickName = document.getElementById('brickName');
const brickDescription = document.getElementById('brickDescription');
const brickColor = document.getElementById('brickColor');
const brickTexture = document.getElementById('brickTexture');
const likeBtn = document.getElementById('likeBtn');
const nopeBtn = document.getElementById('nopeBtn');
const likedCountEl = document.getElementById('likedCount');
const remainingCountEl = document.getElementById('remainingCount');
const endScreen = document.getElementById('endScreen');
const finalLikedCount = document.getElementById('finalLikedCount');
const restartBtn = document.getElementById('restartBtn');
const backgroundImage = document.querySelector('.background-image');
const matchPopup = document.getElementById('matchPopup');
function loadBrick(index) {
if (index >= bricks.length) {
showEndScreen();
return;
}
const brick = bricks[index];
// Reset card position and opacity for smooth entry
card.style.transition = 'none';
card.style.transform = 'translate(0, 0) rotate(0deg)';
card.style.opacity = '0';
// Hide background image when new card loads
if (backgroundImage) {
backgroundImage.style.transition = 'opacity 0.3s ease-in';
backgroundImage.style.opacity = '0';
}
// Update content
brickImage.src = brick.image;
brickImage.alt = brick.name;
brickName.textContent = brick.name;
brickDescription.textContent = brick.description;
brickColor.textContent = brick.color;
brickTexture.textContent = brick.texture;
card.querySelector('.card-overlay').classList.remove('active');
updateStats();
// Fade in the new card smoothly
setTimeout(() => {
card.style.transition = 'opacity 0.3s ease-in';
card.style.opacity = '1';
}, 50);
}
function updateStats() {
likedCountEl.textContent = likedCount;
remainingCountEl.textContent = bricks.length - currentIndex;
}
function swipeCard(direction) {
const overlay = card.querySelector('.card-overlay');
const likeBadge = overlay.querySelector('.like-badge');
const nopeBadge = overlay.querySelector('.nope-badge');
overlay.classList.add('active');
// Set transition for smooth animation
card.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
// Show background image as card swipes away
if (backgroundImage) {
backgroundImage.style.transition = 'opacity 0.4s ease-out';
backgroundImage.style.opacity = '0.10';
}
if (direction === 'right') {
likeBadge.style.display = 'block';
nopeBadge.style.display = 'none';
likedCount++;
updateStats();
// Smoothly animate card off screen
card.style.transform = `translate(400px, 0) rotate(25deg)`;
card.style.opacity = '0';
// Show match popup after card animation, then auto-continue
setTimeout(() => {
showMatchPopup();
// Auto-hide and continue after 2 seconds
setTimeout(() => {
hideMatchPopup();
nextBrick();
}, 2000);
}, 400);
} else {
nopeBadge.style.display = 'block';
likeBadge.style.display = 'none';
// Smoothly animate card off screen
card.style.transform = `translate(-400px, 0) rotate(-25deg)`;
card.style.opacity = '0';
// Load next brick after animation completes
setTimeout(() => {
nextBrick();
}, 400);
}
}
function showMatchPopup() {
if (matchPopup) {
// Set the right profile image to the current brick
const rightProfileImg = document.getElementById('rightProfileImg');
if (rightProfileImg && currentIndex < bricks.length) {
rightProfileImg.src = bricks[currentIndex].image;
}
matchPopup.classList.add('show');
// Prevent body scrolling
document.body.style.overflow = 'hidden';
document.documentElement.style.overflow = 'hidden';
}
}
function hideMatchPopup() {
if (matchPopup) {
matchPopup.classList.remove('show');
// Restore body scrolling
document.body.style.overflow = '';
document.documentElement.style.overflow = '';
}
}
function nextBrick() {
currentIndex++;
loadBrick(currentIndex);
}
function showEndScreen() {
endScreen.classList.add('show');
finalLikedCount.textContent = likedCount;
}
function restart() {
currentIndex = 0;
likedCount = 0;
endScreen.classList.remove('show');
loadBrick(0);
}
// Touch/Mouse events for swiping
card.addEventListener('mousedown', startDrag);
card.addEventListener('touchstart', startDrag);
card.addEventListener('mousemove', drag);
card.addEventListener('touchmove', drag);
card.addEventListener('mouseup', endDrag);
card.addEventListener('touchend', endDrag);
card.addEventListener('mouseleave', endDrag);
function startDrag(e) {
isDragging = true;
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
startX = clientX - card.offsetLeft;
startY = clientY - card.offsetTop;
card.style.transition = 'none';
}
function drag(e) {
if (!isDragging) return;
e.preventDefault();
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
currentX = clientX - startX;
currentY = clientY - startY;
const rotate = currentX / 20;
card.style.transform = `translate(${currentX}px, ${currentY}px) rotate(${rotate}deg)`;
const overlay = card.querySelector('.card-overlay');
if (Math.abs(currentX) > 50) {
overlay.classList.add('active');
if (currentX > 0) {
overlay.querySelector('.like-badge').style.display = 'block';
overlay.querySelector('.nope-badge').style.display = 'none';
} else {
overlay.querySelector('.nope-badge').style.display = 'block';
overlay.querySelector('.like-badge').style.display = 'none';
}
} else {
overlay.classList.remove('active');
}
}
function endDrag() {
if (!isDragging) return;
isDragging = false;
card.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
if (Math.abs(currentX) > 100) {
if (currentX > 0) {
swipeCard('right');
} else {
swipeCard('left');
}
} else {
card.style.transform = 'translate(0, 0) rotate(0deg)';
card.style.opacity = '1';
card.querySelector('.card-overlay').classList.remove('active');
}
currentX = 0;
currentY = 0;
}
// Button events
likeBtn.addEventListener('click', () => swipeCard('right'));
nopeBtn.addEventListener('click', () => swipeCard('left'));
restartBtn.addEventListener('click', restart);
// Initialize
loadBrick(0);