BIS_Reasoning_v1.0 / script.js
nguyenthanhasia's picture
Upload 7 files
f3cdc9d verified
// DOM Content Loaded
document.addEventListener('DOMContentLoaded', function() {
// Mobile Navigation Toggle
const hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('.nav-menu');
hamburger.addEventListener('click', function() {
hamburger.classList.toggle('active');
navMenu.classList.toggle('active');
});
// Close mobile menu when clicking on a link
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('click', () => {
hamburger.classList.remove('active');
navMenu.classList.remove('active');
});
});
// Smooth scrolling for navigation links
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; // Account for fixed navbar
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
});
}
});
});
// Navbar background on scroll
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';
}
});
// Animated counter for hero stats
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();
}
// Intersection Observer for animations
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');
// Animate counters when hero section is visible
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);
// Observe elements for animation
const animatedElements = document.querySelectorAll('.contribution-item, .finding-item, .resource-item, .hero-stats, .example-container, .categories-visual');
animatedElements.forEach(el => observer.observe(el));
// Active navigation link highlighting
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);
// Parallax effect for hero section
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)`;
}
});
// Copy citation to clipboard
const citationBox = document.querySelector('.citation-box');
if (citationBox) {
citationBox.addEventListener('click', function() {
const text = this.textContent;
navigator.clipboard.writeText(text).then(function() {
// Show feedback
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);
});
});
}
// Add hover effects to performance table rows
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)';
});
});
/* Ensure images are visible and properly loaded */
const images = document.querySelectorAll('img[src]');
images.forEach(img => {
img.style.opacity = '1';
img.style.transition = 'opacity 0.3s ease';
// Ensure image is loaded
if (!img.complete) {
img.onload = function() {
this.style.opacity = '1';
};
}
});
// Add scroll progress indicator
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 + '%';
});
// Add smooth fade-in effect to hero title instead of typing
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);
}
// Add floating animation to contribution items
const contributionItems = document.querySelectorAll('.contribution-item');
contributionItems.forEach((item, index) => {
item.style.animationDelay = `${index * 0.1}s`;
item.classList.add('float-animation');
});
// Add CSS for floating 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);
// Add click effects to buttons
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);
});
});
// Add ripple animation CSS
const rippleStyle = document.createElement('style');
rippleStyle.textContent = `
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(rippleStyle);
// Performance optimization: Debounce scroll events
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Apply debouncing to scroll events
const debouncedScrollHandler = debounce(() => {
highlightNavigation();
}, 10);
window.addEventListener('scroll', debouncedScrollHandler);
console.log('BIS Reasoning 1.0 website loaded successfully!');
});