SRI12700's picture
Initial DeepSite commit
cb038bd verified
Raw
History Blame Contribute Delete
8.29 kB
// Initialize Lucide Icons
lucide.createIcons();
// ===== MOBILE MENU =====
const menuBtn = document.getElementById('menuBtn');
const closeMenuBtn = document.getElementById('closeMenu');
const mobileMenu = document.getElementById('mobileMenu');
const mobileLinks = document.querySelectorAll('.mobile-nav-link');
function toggleMenu() {
mobileMenu.classList.toggle('open');
}
menuBtn.addEventListener('click', toggleMenu);
closeMenuBtn.addEventListener('click', toggleMenu);
mobileLinks.forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.remove('open');
});
});
// ===== NAVBAR SCROLL EFFECT =====
const navbar = document.getElementById('navbar');
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
navbar.classList.add('scrolled');
} else {
navbar.classList.remove('scrolled');
}
});
// ===== ACTIVE NAV LINK =====
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
function updateActiveNav() {
const scrollY = window.scrollY + 100;
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.offsetHeight;
const sectionId = section.getAttribute('id');
if (scrollY >= sectionTop && scrollY < sectionTop + sectionHeight) {
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === '#' + sectionId) {
link.classList.add('active');
}
});
// Also update mobile nav
mobileLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === '#' + sectionId) {
link.classList.add('active');
}
});
}
});
}
window.addEventListener('scroll', updateActiveNav);
// ===== SCROLL ANIMATIONS =====
const scrollElements = document.querySelectorAll('.scroll-animate');
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
// Add staggered delay based on element position
setTimeout(() => {
entry.target.classList.add('visible');
}, 100);
observer.unobserve(entry.target);
}
});
},
{
threshold: 0.1,
rootMargin: '0px 0px -50px 0px',
}
);
scrollElements.forEach(el => observer.observe(el));
// ===== SKILL BARS ANIMATION =====
const skillObserver = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const bar = entry.target.querySelector('.skill-bar-fill');
if (bar) {
setTimeout(() => {
bar.classList.add('animate');
}, 200);
}
skillObserver.unobserve(entry.target);
}
});
},
{
threshold: 0.3,
}
);
document.querySelectorAll('.skill-item').forEach(item => {
skillObserver.observe(item);
});
// ===== BACK TO TOP =====
const backToTop = document.getElementById('backToTop');
window.addEventListener('scroll', () => {
if (window.scrollY > 500) {
backToTop.classList.add('visible');
} else {
backToTop.classList.remove('visible');
}
});
backToTop.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// ===== CONTACT FORM =====
const contactForm = document.getElementById('contactForm');
const formSuccess = document.getElementById('formSuccess');
contactForm.addEventListener('submit', (e) => {
e.preventDefault();
// Simple visual feedback
const btn = contactForm.querySelector('button[type="submit"]');
btn.innerHTML = '<span>Sending...</span>';
btn.disabled = true;
setTimeout(() => {
contactForm.reset();
formSuccess.classList.remove('hidden');
formSuccess.style.display = 'block';
btn.innerHTML = '<i data-lucide="send" class="w-4 h-4"></i><span>Send Message</span>';
btn.disabled = false;
lucide.createIcons();
setTimeout(() => {
formSuccess.classList.add('hidden');
formSuccess.style.display = 'none';
}, 4000);
}, 1200);
});
// ===== FILE UPLOAD =====
const fileInput = document.getElementById('fileInput');
const fileDropZone = document.getElementById('fileDropZone');
const fileList = document.getElementById('fileList');
let uploadedFiles = [];
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
function getFileIcon(fileName) {
const ext = fileName.split('.').pop().toLowerCase();
const iconMap = {
pdf: 'file-text', doc: 'file-text', docx: 'file-text', txt: 'file-text',
png: 'image', jpg: 'image', jpeg: 'image', gif: 'image', svg: 'image', webp: 'image',
zip: 'archive', rar: 'archive',
};
return iconMap[ext] || 'file';
}
function renderFileList() {
fileList.innerHTML = '';
uploadedFiles.forEach((file, index) => {
const fileItem = document.createElement('div');
fileItem.className = 'flex items-center justify-between gap-3 p-3 rounded-lg bg-white/[0.03] border border-white/[0.08] group/file transition-all';
fileItem.innerHTML = `
<div class="flex items-center gap-3 min-w-0">
<div class="w-9 h-9 rounded-lg bg-gradient-to-br from-violet-600/20 to-cyan-600/20 flex items-center justify-center flex-shrink-0 border border-violet-500/20">
<i data-lucide="${getFileIcon(file.name)}" class="w-4 h-4 text-violet-400"></i>
</div>
<div class="min-w-0">
<p class="text-sm font-medium text-white truncate">${file.name}</p>
<p class="text-xs text-gray-500">${formatFileSize(file.size)}</p>
</div>
</div>
<button type="button" class="remove-file flex-shrink-0 w-8 h-8 rounded-lg flex items-center justify-center text-gray-500 hover:text-red-400 hover:bg-red-500/10 transition-all" data-index="${index}">
<i data-lucide="x" class="w-4 h-4"></i>
</button>
`;
fileList.appendChild(fileItem);
});
lucide.createIcons();
// Attach remove handlers
fileList.querySelectorAll('.remove-file').forEach(btn => {
btn.addEventListener('click', () => {
const idx = parseInt(btn.getAttribute('data-index'));
uploadedFiles.splice(idx, 1);
renderFileList();
});
});
}
function handleFiles(files) {
for (const file of files) {
if (file.size > 10 * 1024 * 1024) {
alert(`File "${file.name}" exceeds 10MB limit.`);
continue;
}
if (uploadedFiles.length >= 5) {
alert('Maximum 5 files allowed.');
break;
}
uploadedFiles.push(file);
}
fileInput.value = '';
renderFileList();
}
fileInput.addEventListener('change', (e) => {
handleFiles(e.target.files);
});
fileDropZone.addEventListener('dragover', (e) => {
e.preventDefault();
fileDropZone.classList.add('border-violet-500/50', 'bg-violet-500/5');
});
fileDropZone.addEventListener('dragleave', (e) => {
e.preventDefault();
fileDropZone.classList.remove('border-violet-500/50', 'bg-violet-500/5');
});
fileDropZone.addEventListener('drop', (e) => {
e.preventDefault();
fileDropZone.classList.remove('border-violet-500/50', 'bg-violet-500/5');
handleFiles(e.dataTransfer.files);
});
// ===== TYPING EFFECT (simulated with CSS already) =====
// Re-initialize in case dynamic content was added
setTimeout(() => {
lucide.createIcons();
}, 100);
// ===== SMOOTH SCROLL FOR ANCHOR LINKS =====
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
const offset = 80;
const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - offset;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
});
});
// ===== PARALLAX ORBs =====
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
const orbs = document.querySelectorAll('.orb');
orbs.forEach((orb, i) => {
const speed = 0.05 * (i + 1);
orb.style.transform = `translateY(${scrolled * speed}px)`;
});
});