LittleDemon WebShell


Linux server27.hostingraja.org 2.6.32-954.3.5.lve1.4.93.el6.x86_64 #1 SMP Wed Oct 4 17:04:29 UTC 2023 x86_64
Path : /home/udaipurk/www/websites/rohitnagda.com/js/
File Upload :
Command :
Current File : /home/udaipurk/www/websites/rohitnagda.com/js/scripts.js

  /* ────────────────────────────────────────────────────────
     NAVBAR: scroll + active section
  ──────────────────────────────────────────────────────── */
  const mainNav = document.getElementById('mainNav');
  const navLinks = document.querySelectorAll('[data-nav]');
  const sections = document.querySelectorAll('section[id]');

  window.addEventListener('scroll', () => {
    mainNav.classList.toggle('scrolled', window.scrollY > 50);
    let current = '';
    sections.forEach(s => {
      if (window.scrollY >= s.offsetTop - 120) current = s.id;
    });
    navLinks.forEach(a => {
      a.classList.toggle('active', a.getAttribute('href') === '#' + current);
    });
  }, { passive: true });

  /* ────────────────────────────────────────────────────────
     MOBILE NAV
  ──────────────────────────────────────────────────────── */
  const navToggle = document.getElementById('navToggle');
  const mobileNav = document.getElementById('mobileNav');
  const navOverlay = document.getElementById('navOverlay');
  const mobileNavClose = document.getElementById('mobileNavClose');

  function openNav() { mobileNav.classList.add('open'); navOverlay.classList.add('open'); document.body.style.overflow='hidden'; }
  function closeNav() { mobileNav.classList.remove('open'); navOverlay.classList.remove('open'); document.body.style.overflow=''; }

  navToggle.addEventListener('click', openNav);
  mobileNavClose.addEventListener('click', closeNav);
  navOverlay.addEventListener('click', closeNav);
  document.querySelectorAll('.mobile-link').forEach(a => a.addEventListener('click', closeNav));

  /* ────────────────────────────────────────────────────────
     REVEAL ON SCROLL
  ──────────────────────────────────────────────────────── */
  const revealObs = new IntersectionObserver((entries) => {
    entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('visible'); revealObs.unobserve(e.target); } });
  }, { threshold: 0.1 });
  document.querySelectorAll('.reveal').forEach(el => revealObs.observe(el));

  /* ────────────────────────────────────────────────────────
     TIMELINE REVEAL
  ──────────────────────────────────────────────────────── */
  const tlObs = new IntersectionObserver((entries) => {
    entries.forEach((e, i) => {
      if (e.isIntersecting) {
        setTimeout(() => e.target.classList.add('visible'), i * 100);
        tlObs.unobserve(e.target);
      }
    });
  }, { threshold: 0.15 });
  document.querySelectorAll('.tl-item').forEach(el => tlObs.observe(el));

  /* ────────────────────────────────────────────────────────
     SKILL BARS ANIMATE
  ──────────────────────────────────────────────────────── */
  const skillObs = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        const pct = e.target.dataset.pct;
        e.target.querySelector('.skill-fill').style.width = pct + '%';
        skillObs.unobserve(e.target);
      }
    });
  }, { threshold: 0.3 });
  document.querySelectorAll('.skill-row').forEach(el => skillObs.observe(el));

  /* ────────────────────────────────────────────────────────
     LANGUAGE RINGS ANIMATE
  ──────────────────────────────────────────────────────── */
  const CIRCUMFERENCE = 2 * Math.PI * 45; // r=45
  const ringObs = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        const pct = parseInt(e.target.dataset.pct) / 100;
        const fill = e.target.querySelector('.fill');
        fill.style.strokeDasharray = CIRCUMFERENCE;
        fill.style.strokeDashoffset = CIRCUMFERENCE * (1 - pct);
        ringObs.unobserve(e.target);
      }
    });
  }, { threshold: 0.3 });
  document.querySelectorAll('.lang-ring').forEach(el => {
    const fill = el.querySelector('.fill');
    fill.style.strokeDasharray = CIRCUMFERENCE;
    fill.style.strokeDashoffset = CIRCUMFERENCE;
    ringObs.observe(el);
  });

  /* ────────────────────────────────────────────────────────
     TESTIMONIAL SLIDER
  ──────────────────────────────────────────────────────── */
  let tIdx = 0;
  const tCards = document.querySelectorAll('.testimonial-card');
  const tDots = document.querySelectorAll('.t-dot');

  function showTestimonial(idx) {
    tCards.forEach((c, i) => {
      c.style.display = i === idx ? 'block' : 'none';
      c.classList.toggle('active', i === idx);
    });
    tDots.forEach((d, i) => d.classList.toggle('active', i === idx));
    tIdx = idx;
  }
  showTestimonial(0);
  tDots.forEach(d => d.addEventListener('click', () => showTestimonial(parseInt(d.dataset.idx))));
  setInterval(() => showTestimonial((tIdx + 1) % tCards.length), 5000);

  /* ────────────────────────────────────────────────────────
     PORTFOLIO FILTER
  ──────────────────────────────────────────────────────── */
  const filterBtns = document.querySelectorAll('.filter-btn');
  const bentoItems = document.querySelectorAll('.bento-item');

  filterBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      filterBtns.forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      const filter = btn.dataset.filter;
      bentoItems.forEach(item => {
        const match = filter === 'all' || item.dataset.filter === filter;
        item.classList.toggle('hidden', !match);
      });
    });
  });

  /* ────────────────────────────────────────────────────────
     LIGHTBOX
  ──────────────────────────────────────────────────────── */
  const lightbox = document.getElementById('lightbox');
  const lbImg = document.getElementById('lightbox-img');
  const lbClose = document.getElementById('lightbox-close');
  const lbExpand = document.getElementById('lightbox-expand');
  const lbPrev = document.getElementById('lb-prev');
  const lbNext = document.getElementById('lb-next');

  let lbImages = [];
  let lbCurrent = 0;

  function openLightbox(src, imgs, idx) {
    lbImages = imgs;
    lbCurrent = idx;
    lbImg.src = src;
    lightbox.classList.add('open');
    document.body.style.overflow = 'hidden';
  }
  function closeLightbox() {
    lightbox.classList.remove('open');
    document.body.style.overflow = '';
  }
  lbClose.addEventListener('click', closeLightbox);
  lightbox.addEventListener('click', e => { if (e.target === lightbox) closeLightbox(); });
  lbExpand.addEventListener('click', (e) => {
    e.stopPropagation();
    window.open(lbImg.src, '_blank');
  });
  lbPrev.addEventListener('click', (e) => {
    e.stopPropagation();
    lbCurrent = (lbCurrent - 1 + lbImages.length) % lbImages.length;
    lbImg.src = lbImages[lbCurrent];
  });
  lbNext.addEventListener('click', (e) => {
    e.stopPropagation();
    lbCurrent = (lbCurrent + 1) % lbImages.length;
    lbImg.src = lbImages[lbCurrent];
  });
  document.addEventListener('keydown', e => {
    if (!lightbox.classList.contains('open')) return;
    if (e.key === 'Escape') closeLightbox();
    if (e.key === 'ArrowLeft') lbPrev.click();
    if (e.key === 'ArrowRight') lbNext.click();
  });

  /* ────────────────────────────────────────────────────────
     BENTO ITEM CLICK HANDLING
  ──────────────────────────────────────────────────────── */
  bentoItems.forEach(item => {
    item.addEventListener('click', () => {
      if (item.classList.contains('hidden')) return;

      const isCase = item.dataset.case === 'true';
      if (isCase) {
        const href = item.dataset.href;
        window.open(href, '_blank');
        return;
      }

      const src = item.dataset.src;
      if (!src) return;

      // collect all visible non-case items for lightbox navigation
      const visibleImgs = Array.from(bentoItems)
        .filter(i => !i.classList.contains('hidden') && i.dataset.src && i.dataset.case !== 'true')
        .map(i => i.dataset.src);
      const idx = visibleImgs.indexOf(src);
      openLightbox(src, visibleImgs, idx !== -1 ? idx : 0);
    });
  });

  /* ────────────────────────────────────────────────────────
     PREVENT IMAGE DRAG
  ──────────────────────────────────────────────────────── */
  document.querySelectorAll('img').forEach(img => {
    img.addEventListener('dragstart', e => e.preventDefault());
  });

LittleDemon - FACEBOOK
[ KELUAR ]