summaryrefslogtreecommitdiff
path: root/static/script.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/script.js')
-rw-r--r--static/script.js157
1 files changed, 157 insertions, 0 deletions
diff --git a/static/script.js b/static/script.js
new file mode 100644
index 0000000..e1fd02c
--- /dev/null
+++ b/static/script.js
@@ -0,0 +1,157 @@
+// 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) {
+ target.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ });
+ }
+ });
+});
+
+// Mobile menu toggle
+const hamburger = document.querySelector('.hamburger');
+const navMenu = document.querySelector('.nav-menu');
+
+hamburger.addEventListener('click', () => {
+ hamburger.classList.toggle('active');
+ navMenu.classList.toggle('active');
+});
+
+// Close mobile menu when clicking on a link
+document.querySelectorAll('.nav-link').forEach(n => n.addEventListener('click', () => {
+ hamburger.classList.remove('active');
+ navMenu.classList.remove('active');
+}));
+
+// Navbar background on scroll
+window.addEventListener('scroll', () => {
+ const navbar = document.querySelector('.navbar');
+ if (window.scrollY > 50) {
+ navbar.style.background = 'rgba(255, 255, 255, 0.98)';
+ } else {
+ navbar.style.background = 'rgba(255, 255, 255, 0.95)';
+ }
+});
+
+// Intersection Observer for animations
+const observerOptions = {
+ threshold: 0.1,
+ 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)';
+ }
+ });
+}, observerOptions);
+
+// Observe elements for animation
+document.querySelectorAll('.project-card, .stat, .about-text').forEach(el => {
+ el.style.opacity = '0';
+ el.style.transform = 'translateY(30px)';
+ el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
+ observer.observe(el);
+});
+
+// Form submission
+document.querySelector('.contact-form').addEventListener('submit', function(e) {
+ e.preventDefault();
+
+ // Get form data
+ const formData = new FormData(this);
+ const name = this.querySelector('input[type="text"]').value;
+ const email = this.querySelector('input[type="email"]').value;
+ const message = this.querySelector('textarea').value;
+
+ // Simple validation
+ if (!name || !email || !message) {
+ alert('Please fill in all fields');
+ return;
+ }
+
+ // Simulate form submission
+ const submitBtn = this.querySelector('button[type="submit"]');
+ const originalText = submitBtn.textContent;
+
+ submitBtn.textContent = 'Sending...';
+ submitBtn.disabled = true;
+
+ setTimeout(() => {
+ alert('Thank you for your message! I\'ll get back to you soon.');
+ this.reset();
+ submitBtn.textContent = originalText;
+ submitBtn.disabled = false;
+ }, 2000);
+});
+
+// Add typing animation to hero title
+const heroTitle = document.querySelector('.hero-title');
+if (heroTitle) {
+ const text = heroTitle.innerHTML;
+ heroTitle.innerHTML = '';
+
+ let i = 0;
+ const typeWriter = () => {
+ if (i < text.length) {
+ heroTitle.innerHTML += text.charAt(i);
+ i++;
+ setTimeout(typeWriter, 50);
+ }
+ };
+
+ // Start typing animation after page load
+ window.addEventListener('load', () => {
+ setTimeout(typeWriter, 500);
+ });
+}
+
+// Parallax effect for floating cards
+window.addEventListener('scroll', () => {
+ const scrolled = window.pageYOffset;
+ const parallaxElements = document.querySelectorAll('.floating-card');
+
+ parallaxElements.forEach((element, index) => {
+ const speed = 0.5 + (index * 0.1);
+ const yPos = -(scrolled * speed);
+ element.style.transform = `translateY(${yPos}px)`;
+ });
+});
+
+// Add mobile menu styles dynamically
+const style = document.createElement('style');
+style.textContent = `
+ @media (max-width: 768px) {
+ .nav-menu.active {
+ display: flex;
+ position: absolute;
+ top: 100%;
+ left: 0;
+ width: 100%;
+ background: white;
+ flex-direction: column;
+ padding: 1rem 2rem;
+ box-shadow: var(--shadow);
+ border-top: 1px solid var(--border);
+ }
+
+ .hamburger.active span:nth-child(1) {
+ transform: rotate(-45deg) translate(-5px, 6px);
+ }
+
+ .hamburger.active span:nth-child(2) {
+ opacity: 0;
+ }
+
+ .hamburger.active span:nth-child(3) {
+ transform: rotate(45deg) translate(-5px, -6px);
+ }
+ }
+`;
+document.head.appendChild(style);