/* ============================================
PREGNANCY PILLOW STORE - Advanced JavaScript
Features: Parallax Scrolling, Animations, Interactions
============================================ */
(function() {
'use strict';
// Configuration
const CONFIG = {
parallaxIntensity: 0.5,
animationDelay: 100,
scrollThreshold: 0.1
};
// ============================================
// PARALLAX SCROLLING EFFECT
// ============================================
class ParallaxManager {
constructor() {
this.parallaxElements = document.querySelectorAll('.parallax-section');
this.init();
}
init() {
window.addEventListener('scroll', () => this.updateParallax());
this.updateParallax();
}
updateParallax() {
this.parallaxElements.forEach(element => {
const elementPosition = element.getBoundingClientRect().top;
const scrollAmount = window.scrollY;
const parallaxAmount = (elementPosition * CONFIG.parallaxIntensity);
// Create parallax effect on background
element.style.backgroundPosition = `center ${parallaxAmount}px`;
// Add fade-in effect as user scrolls
const opacity = Math.max(0, 1 - (elementPosition / window.innerHeight));
element.style.opacity = opacity;
});
}
}
// ============================================
// SCROLL ANIMATION OBSERVER
// ============================================
class ScrollAnimationObserver {
constructor() {
this.elements = document.querySelectorAll('.feature-card, .testimonial-card');
this.init();
}
init() {
const observerOptions = {
threshold: CONFIG.scrollThreshold,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
observer.unobserve(entry.target);
}
});
}, observerOptions);
this.elements.forEach(element => {
observer.observe(element);
});
}
}
// ============================================
// HERO SECTION - OPACITY SLIDE EFFECT
// ============================================
class HeroEffects {
constructor() {
this.heroSection = document.querySelector('.hero-section');
if (!this.heroSection) return;
this.init();
}
init() {
window.addEventListener('scroll', () => this.updateHeroEffect());
}
updateHeroEffect() {
if (!this.heroSection) return;
const scrollY = window.scrollY;
const heroHeight = this.heroSection.offsetHeight;
const opacity = Math.max(0, 1 - (scrollY / (heroHeight * 0.5)));
this.heroSection.style.opacity = opacity;
this.heroSection.style.transform = `translateY(${scrollY * 0.5}px)`;
}
}
// ============================================
// COUNTER ANIMATION (for stats)
// ============================================
class CounterAnimation {
constructor(element, targetNumber, duration = 2000) {
this.element = element;
this.target = targetNumber;
this.duration = duration;
this.current = 0;
this.hasAnimated = false;
}
animateCount() {
if (this.hasAnimated) return;
const increment = this.target / (this.duration / 16);
const interval = setInterval(() => {
this.current += increment;
if (this.current >= this.target) {
this.current = this.target;
clearInterval(interval);
this.hasAnimated = true;
}
this.element.textContent = Math.floor(this.current).toLocaleString();
}, 16);
}
}
// ============================================
// SMOOTH SCROLL TO SECTION
// ============================================
class SmoothScroll {
constructor() {
this.setupScrollLinks();
}
setupScrollLinks() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(anchor.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
}
// ============================================
// LAZY LOAD IMAGES
// ============================================
class LazyLoadImages {
constructor() {
this.init();
}
init() {
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.add('loaded');
imageObserver.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
imageObserver.observe(img);
});
}
}
// ============================================
// HOVER EFFECTS ON CARDS
// ============================================
class CardHoverEffects {
constructor() {
this.setupHoverEffects();
}
setupHoverEffects() {
const cards = document.querySelectorAll('.feature-card, .testimonial-card');
cards.forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transition = 'all 0.3s ease';
});
card.addEventListener('mouseleave', function() {
this.style.transition = 'all 0.3s ease';
});
});
}
}
// ============================================
// NOTIFICATION TOAST (for CTA clicks)
// ============================================
class ToastNotification {
static show(message, duration = 3000, type = 'success') {
const toast = document.createElement('div');
toast.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
background: ${type === 'success' ? '#27ae60' : '#e74c3c'};
color: white;
padding: 15px 25px;
border-radius: 8px;
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
z-index: 10000;
animation: slideInRight 0.3s ease;
font-weight: 600;
`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => {
toast.style.animation = 'slideInLeft 0.3s ease reverse';
setTimeout(() => toast.remove(), 300);
}, duration);
}
}
// ============================================
// BUTTON INTERACTIONS
// ============================================
class ButtonInteractions {
constructor() {
this.setupButtons();
}
setupButtons() {
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener('click', (e) => {
// Add ripple effect
this.createRipple(e, btn);
// Show feedback
const message = btn.classList.contains('btn-primary')
? 'Redirecting to shop...'
: 'Taking you to details...';
ToastNotification.show(message, 2000);
});
});
}
createRipple(event, button) {
const ripple = document.createElement('span');
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left - size / 2;
const y = event.clientY - rect.top - size / 2;
ripple.style.cssText = `
position: absolute;
width: ${size}px;
height: ${size}px;
background: rgba(255,255,255,0.5);
border-radius: 50%;
left: ${x}px;
top: ${y}px;
pointer-events: none;
animation: ripple 0.6s ease-out;
`;
button.style.position = 'relative';
button.style.overflow = 'hidden';
button.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
}
}
// ============================================
// SCROLL TO TOP BUTTON
// ============================================
class ScrollToTopButton {
constructor() {
this.createButton();
this.setupListener();
}
createButton() {
const btn = document.createElement('button');
btn.id = 'scroll-to-top';
btn.innerHTML = '↑';
btn.style.cssText = `
position: fixed;
bottom: 30px;
right: 30px;
width: 50px;
height: 50px;
background: linear-gradient(135deg, #1e5ba8, #2e7bb9);
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
z-index: 999;
font-size: 1.5rem;
box-shadow: 0 5px 15px rgba(30, 91, 168, 0.4);
`;
document.body.appendChild(btn);
btn.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
btn.style.opacity = '1';
btn.style.visibility = 'visible';
} else {
btn.style.opacity = '0';
btn.style.visibility = 'hidden';
}
});
}
}
// ============================================
// RIPPLE ANIMATION KEYFRAME (inject into styles)
// ============================================
function injectRippleAnimation() {
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(style);
}
// ============================================
// INITIALIZE ALL FEATURES
// ============================================
document.addEventListener('DOMContentLoaded', () => {
// Inject animations
injectRippleAnimation();
// Initialize managers
new ParallaxManager();
new ScrollAnimationObserver();
new HeroEffects();
new SmoothScroll();
new LazyLoadImages();
new CardHoverEffects();
new ButtonInteractions();
new ScrollToTopButton();
console.log('✓ Pregnancy Pillow Store - All features loaded!');
});
// ============================================
// PERFORMANCE: Throttle scroll events
// ============================================
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
// Throttle parallax updates for better performance
const throttledScroll = throttle(() => {
window.dispatchEvent(new Event('throttledScroll'));
}, 50);
window.addEventListener('scroll', throttledScroll);
})();