185 lines
6.1 KiB
JavaScript
185 lines
6.1 KiB
JavaScript
/* ============================================================
|
|
ChronoSeal Website — app.js
|
|
Core runtime: header scroll, mobile nav, scroll animations,
|
|
code copy, back-to-top, keyboard shortcuts
|
|
============================================================ */
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
/* ---- Header scroll state ---- */
|
|
var header = document.querySelector('.navbar');
|
|
if (header) {
|
|
var onScroll = function () {
|
|
header.classList.toggle('scrolled', window.scrollY > 20);
|
|
};
|
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
onScroll();
|
|
}
|
|
|
|
/* ---- Enhanced Mobile nav toggle ---- */
|
|
var toggle = document.querySelector('.nav-toggle');
|
|
var navLinks = document.querySelector('.nav-links');
|
|
if (toggle && navLinks) {
|
|
var menuIcon = toggle.querySelector('i');
|
|
toggle.addEventListener('click', function () {
|
|
var isActive = navLinks.classList.contains('active');
|
|
if (isActive) {
|
|
navLinks.classList.remove('active');
|
|
if (menuIcon) {
|
|
menuIcon.classList.remove('fa-times');
|
|
menuIcon.classList.add('fa-bars');
|
|
}
|
|
} else {
|
|
navLinks.classList.add('active');
|
|
if (menuIcon) {
|
|
menuIcon.classList.remove('fa-bars');
|
|
menuIcon.classList.add('fa-times');
|
|
}
|
|
}
|
|
});
|
|
|
|
// Close nav on link click
|
|
navLinks.querySelectorAll('a').forEach(function (a) {
|
|
a.addEventListener('click', function () {
|
|
navLinks.classList.remove('active');
|
|
if (menuIcon) {
|
|
menuIcon.classList.remove('fa-times');
|
|
menuIcon.classList.add('fa-bars');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/* ---- Doc sidebar mobile toggle ---- */
|
|
var sidebarToggle = document.querySelector('.doc-sidebar-toggle');
|
|
var sidebar = document.querySelector('.doc-sidebar');
|
|
if (sidebarToggle && sidebar) {
|
|
sidebarToggle.addEventListener('click', function () {
|
|
sidebar.classList.toggle('open');
|
|
});
|
|
// Close sidebar on link click (mobile)
|
|
sidebar.querySelectorAll('.doc-nav-item').forEach(function (a) {
|
|
a.addEventListener('click', function () {
|
|
if (window.innerWidth <= 900) sidebar.classList.remove('open');
|
|
});
|
|
});
|
|
}
|
|
|
|
/* ---- Intersection Observer for Scroll Animations ---- */
|
|
if ('IntersectionObserver' in window) {
|
|
var observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' };
|
|
var observer = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('in-view');
|
|
observer.unobserve(entry.target);
|
|
}
|
|
});
|
|
}, observerOptions);
|
|
|
|
// Observe all animated elements
|
|
document.querySelectorAll('.animate, .card, .stat-card, .step').forEach(function (el) {
|
|
if (!el.classList.contains('animate')) {
|
|
el.classList.add('animate');
|
|
}
|
|
observer.observe(el);
|
|
});
|
|
}
|
|
|
|
/* ---- Code block copy buttons ---- */
|
|
document.querySelectorAll('.code-copy-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
var pre = btn.closest('.code-block').querySelector('pre');
|
|
if (!pre) return;
|
|
var text = pre.textContent;
|
|
if (navigator.clipboard) {
|
|
navigator.clipboard.writeText(text).then(function () {
|
|
btn.textContent = 'Copied!';
|
|
setTimeout(function () { btn.textContent = 'Copy'; }, 1500);
|
|
});
|
|
} else {
|
|
// Fallback
|
|
var ta = document.createElement('textarea');
|
|
ta.value = text;
|
|
ta.style.cssText = 'position:fixed;left:-999px';
|
|
document.body.appendChild(ta);
|
|
ta.select();
|
|
document.execCommand('copy');
|
|
document.body.removeChild(ta);
|
|
btn.textContent = 'Copied!';
|
|
setTimeout(function () { btn.textContent = 'Copy'; }, 1500);
|
|
}
|
|
});
|
|
});
|
|
|
|
/* ---- Back to top ---- */
|
|
var btt = document.querySelector('.back-to-top');
|
|
if (btt) {
|
|
window.addEventListener('scroll', function () {
|
|
btt.classList.toggle('visible', window.scrollY > 400);
|
|
}, { passive: true });
|
|
btt.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
});
|
|
}
|
|
|
|
/* ---- Keyboard shortcut: / or Ctrl+K for search ---- */
|
|
document.addEventListener('keydown', function (e) {
|
|
if (e.key === '/' && !isInput(e.target)) {
|
|
e.preventDefault();
|
|
if (typeof ChronoSearch !== 'undefined') ChronoSearch.open();
|
|
}
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
|
e.preventDefault();
|
|
if (typeof ChronoSearch !== 'undefined') ChronoSearch.open();
|
|
}
|
|
if (e.key === 'Escape') {
|
|
if (typeof ChronoSearch !== 'undefined') ChronoSearch.close();
|
|
}
|
|
});
|
|
|
|
function isInput(el) {
|
|
var tag = el.tagName;
|
|
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
|
|
}
|
|
|
|
/* ---- Nav dropdown (desktop hover + mobile tap) ---- */
|
|
document.querySelectorAll('.nav-dropdown').forEach(function (dd) {
|
|
var trigger = dd.querySelector('.nav-link');
|
|
if (!trigger) return;
|
|
trigger.addEventListener('click', function (e) {
|
|
if (window.innerWidth <= 768) {
|
|
e.preventDefault();
|
|
dd.classList.toggle('open');
|
|
}
|
|
});
|
|
});
|
|
|
|
/* ---- Active nav link highlight ---- */
|
|
var currentPage = window.location.pathname.split('/').pop() || 'index.html';
|
|
document.querySelectorAll('.nav-links a, .doc-nav-item').forEach(function (link) {
|
|
var href = link.getAttribute('href');
|
|
if (!href) return;
|
|
var linkPage = href.split('/').pop().split('#')[0] || 'index.html';
|
|
if (linkPage === currentPage) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
|
|
/* ---- Smooth anchor scroll ---- */
|
|
document.querySelectorAll('a[href^="#"]').forEach(function (a) {
|
|
a.addEventListener('click', function (e) {
|
|
var id = a.getAttribute('href').substring(1);
|
|
var target = document.getElementById(id);
|
|
if (target) {
|
|
e.preventDefault();
|
|
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
history.pushState(null, '', '#' + id);
|
|
}
|
|
});
|
|
});
|
|
|
|
})();
|