|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
const hamburger = document.querySelector('.hamburger'); |
|
const navMenu = document.querySelector('.nav-menu'); |
|
|
|
hamburger.addEventListener('click', function() { |
|
hamburger.classList.toggle('active'); |
|
navMenu.classList.toggle('active'); |
|
}); |
|
|
|
|
|
document.querySelectorAll('.nav-link').forEach(link => { |
|
link.addEventListener('click', () => { |
|
hamburger.classList.remove('active'); |
|
navMenu.classList.remove('active'); |
|
}); |
|
}); |
|
|
|
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => { |
|
anchor.addEventListener('click', function (e) { |
|
e.preventDefault(); |
|
const target = document.querySelector(this.getAttribute('href')); |
|
if (target) { |
|
const offsetTop = target.offsetTop - 70; |
|
window.scrollTo({ |
|
top: offsetTop, |
|
behavior: 'smooth' |
|
}); |
|
} |
|
}); |
|
}); |
|
|
|
|
|
const navbar = document.querySelector('.navbar'); |
|
window.addEventListener('scroll', function() { |
|
if (window.scrollY > 50) { |
|
navbar.style.background = 'rgba(255, 255, 255, 0.98)'; |
|
navbar.style.boxShadow = '0 2px 20px rgba(0, 0, 0, 0.1)'; |
|
} else { |
|
navbar.style.background = 'rgba(255, 255, 255, 0.95)'; |
|
navbar.style.boxShadow = 'none'; |
|
} |
|
}); |
|
|
|
|
|
function animateCounter(element, target, duration = 2000) { |
|
let start = 0; |
|
const increment = target / (duration / 16); |
|
|
|
function updateCounter() { |
|
start += increment; |
|
if (start < target) { |
|
element.textContent = Math.floor(start); |
|
requestAnimationFrame(updateCounter); |
|
} else { |
|
element.textContent = target; |
|
} |
|
} |
|
|
|
updateCounter(); |
|
} |
|
|
|
|
|
const observerOptions = { |
|
threshold: 0.1, |
|
rootMargin: '0px 0px -50px 0px' |
|
}; |
|
|
|
const observer = new IntersectionObserver(function(entries) { |
|
entries.forEach(entry => { |
|
if (entry.isIntersecting) { |
|
entry.target.classList.add('fade-in-up'); |
|
|
|
|
|
if (entry.target.classList.contains('hero-stats')) { |
|
const counters = entry.target.querySelectorAll('.stat-number'); |
|
counters.forEach(counter => { |
|
const target = parseInt(counter.getAttribute('data-target')); |
|
animateCounter(counter, target); |
|
}); |
|
} |
|
|
|
observer.unobserve(entry.target); |
|
} |
|
}); |
|
}, observerOptions); |
|
|
|
|
|
const animatedElements = document.querySelectorAll('.contribution-item, .finding-item, .resource-item, .hero-stats, .example-container, .categories-visual'); |
|
animatedElements.forEach(el => observer.observe(el)); |
|
|
|
|
|
const sections = document.querySelectorAll('section[id]'); |
|
const navLinks = document.querySelectorAll('.nav-link'); |
|
|
|
function highlightNavigation() { |
|
let current = ''; |
|
sections.forEach(section => { |
|
const sectionTop = section.offsetTop - 100; |
|
const sectionHeight = section.clientHeight; |
|
if (window.scrollY >= sectionTop && window.scrollY < sectionTop + sectionHeight) { |
|
current = section.getAttribute('id'); |
|
} |
|
}); |
|
|
|
navLinks.forEach(link => { |
|
link.classList.remove('active'); |
|
if (link.getAttribute('href') === `#${current}`) { |
|
link.classList.add('active'); |
|
} |
|
}); |
|
} |
|
|
|
window.addEventListener('scroll', highlightNavigation); |
|
|
|
|
|
const hero = document.querySelector('.hero'); |
|
window.addEventListener('scroll', function() { |
|
const scrolled = window.pageYOffset; |
|
const rate = scrolled * -0.5; |
|
if (hero) { |
|
hero.style.transform = `translateY(${rate}px)`; |
|
} |
|
}); |
|
|
|
|
|
const citationBox = document.querySelector('.citation-box'); |
|
if (citationBox) { |
|
citationBox.addEventListener('click', function() { |
|
const text = this.textContent; |
|
navigator.clipboard.writeText(text).then(function() { |
|
|
|
const feedback = document.createElement('div'); |
|
feedback.textContent = 'Citation copied to clipboard!'; |
|
feedback.style.cssText = ` |
|
position: fixed; |
|
top: 20px; |
|
right: 20px; |
|
background: #10b981; |
|
color: white; |
|
padding: 1rem 2rem; |
|
border-radius: 10px; |
|
z-index: 10000; |
|
animation: slideInRight 0.3s ease; |
|
`; |
|
document.body.appendChild(feedback); |
|
|
|
setTimeout(() => { |
|
feedback.remove(); |
|
}, 3000); |
|
}); |
|
}); |
|
} |
|
|
|
|
|
const tableRows = document.querySelectorAll('.performance-table tbody tr'); |
|
tableRows.forEach(row => { |
|
row.addEventListener('mouseenter', function() { |
|
this.style.backgroundColor = 'rgba(37, 99, 235, 0.05)'; |
|
this.style.transform = 'scale(1.02)'; |
|
this.style.transition = 'all 0.3s ease'; |
|
}); |
|
|
|
row.addEventListener('mouseleave', function() { |
|
if (!this.classList.contains('top-performer')) { |
|
this.style.backgroundColor = ''; |
|
} |
|
this.style.transform = 'scale(1)'; |
|
}); |
|
}); |
|
|
|
|
|
const images = document.querySelectorAll('img[src]'); |
|
images.forEach(img => { |
|
img.style.opacity = '1'; |
|
img.style.transition = 'opacity 0.3s ease'; |
|
|
|
|
|
if (!img.complete) { |
|
img.onload = function() { |
|
this.style.opacity = '1'; |
|
}; |
|
} |
|
}); |
|
|
|
const progressBar = document.createElement('div'); |
|
progressBar.style.cssText = ` |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 0%; |
|
height: 3px; |
|
background: linear-gradient(90deg, #667eea, #764ba2); |
|
z-index: 10000; |
|
transition: width 0.1s ease; |
|
`; |
|
document.body.appendChild(progressBar); |
|
|
|
window.addEventListener('scroll', function() { |
|
const scrollTop = window.pageYOffset; |
|
const docHeight = document.body.scrollHeight - window.innerHeight; |
|
const scrollPercent = (scrollTop / docHeight) * 100; |
|
progressBar.style.width = scrollPercent + '%'; |
|
}); |
|
|
|
|
|
const heroTitle = document.querySelector('.hero-title'); |
|
if (heroTitle) { |
|
heroTitle.style.opacity = '0'; |
|
heroTitle.style.transform = 'translateY(30px)'; |
|
heroTitle.style.transition = 'opacity 1s ease, transform 1s ease'; |
|
|
|
setTimeout(() => { |
|
heroTitle.style.opacity = '1'; |
|
heroTitle.style.transform = 'translateY(0)'; |
|
}, 300); |
|
} |
|
|
|
|
|
const contributionItems = document.querySelectorAll('.contribution-item'); |
|
contributionItems.forEach((item, index) => { |
|
item.style.animationDelay = `${index * 0.1}s`; |
|
item.classList.add('float-animation'); |
|
}); |
|
|
|
|
|
const style = document.createElement('style'); |
|
style.textContent = ` |
|
@keyframes float { |
|
0%, 100% { transform: translateY(0px); } |
|
50% { transform: translateY(-10px); } |
|
} |
|
|
|
.float-animation { |
|
animation: float 3s ease-in-out infinite; |
|
} |
|
|
|
@keyframes slideInRight { |
|
from { transform: translateX(100%); opacity: 0; } |
|
to { transform: translateX(0); opacity: 1; } |
|
} |
|
|
|
.nav-link.active { |
|
color: var(--primary-color); |
|
} |
|
|
|
.nav-link.active::after { |
|
width: 100%; |
|
} |
|
`; |
|
document.head.appendChild(style); |
|
|
|
|
|
const buttons = document.querySelectorAll('.btn, .resource-link'); |
|
buttons.forEach(button => { |
|
button.addEventListener('click', function(e) { |
|
const ripple = document.createElement('span'); |
|
const rect = this.getBoundingClientRect(); |
|
const size = Math.max(rect.width, rect.height); |
|
const x = e.clientX - rect.left - size / 2; |
|
const y = e.clientY - rect.top - size / 2; |
|
|
|
ripple.style.cssText = ` |
|
position: absolute; |
|
width: ${size}px; |
|
height: ${size}px; |
|
left: ${x}px; |
|
top: ${y}px; |
|
background: rgba(255, 255, 255, 0.3); |
|
border-radius: 50%; |
|
transform: scale(0); |
|
animation: ripple 0.6s linear; |
|
pointer-events: none; |
|
`; |
|
|
|
this.style.position = 'relative'; |
|
this.style.overflow = 'hidden'; |
|
this.appendChild(ripple); |
|
|
|
setTimeout(() => { |
|
ripple.remove(); |
|
}, 600); |
|
}); |
|
}); |
|
|
|
|
|
const rippleStyle = document.createElement('style'); |
|
rippleStyle.textContent = ` |
|
@keyframes ripple { |
|
to { |
|
transform: scale(4); |
|
opacity: 0; |
|
} |
|
} |
|
`; |
|
document.head.appendChild(rippleStyle); |
|
|
|
|
|
function debounce(func, wait) { |
|
let timeout; |
|
return function executedFunction(...args) { |
|
const later = () => { |
|
clearTimeout(timeout); |
|
func(...args); |
|
}; |
|
clearTimeout(timeout); |
|
timeout = setTimeout(later, wait); |
|
}; |
|
} |
|
|
|
|
|
const debouncedScrollHandler = debounce(() => { |
|
highlightNavigation(); |
|
}, 10); |
|
|
|
window.addEventListener('scroll', debouncedScrollHandler); |
|
|
|
console.log('BIS Reasoning 1.0 website loaded successfully!'); |
|
}); |
|
|
|
|