Files
romfast-website/professional-theme.js
Marius Mutu 2ce691d166 Add Serena project configuration and update website files
- Configure Serena AI coding assistant with TypeScript language support
- Update gitignore patterns and website content
- Enhance professional theme JavaScript functionality
- Update multiple pages across menu and ROA sections

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 22:30:36 +03:00

421 lines
13 KiB
JavaScript

// Professional Theme JavaScript - Romfast Applications
// This file contains all interactive functionality for the professional theme
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
initializeProfessionalTheme();
});
function initializeProfessionalTheme() {
// Initialize all components
initializeLucideIcons();
initializeThemeToggle();
initializeMobileMenu();
initializeCardAnimations();
initializeScrollAnimations();
initializeButtonEffects();
initializeHeroAnimations();
initializeSmoothScrolling();
initializeWebPSupport();
}
// Initialize Lucide icons
function initializeLucideIcons() {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
}
// Enhanced theme toggle functionality
function initializeThemeToggle() {
const themeToggle = document.getElementById('theme-toggle');
const body = document.body;
if (!themeToggle) return;
// Check for saved theme preference or default to light mode
const currentTheme = localStorage.getItem('theme') || 'light';
if (currentTheme === 'dark') {
body.classList.add('dark-mode');
themeToggle.innerHTML = '<i data-lucide="moon" class="w-5 h-5"></i>';
lucide.createIcons();
}
themeToggle.addEventListener('click', () => {
body.classList.toggle('dark-mode');
// Update icon and save preference
if (body.classList.contains('dark-mode')) {
themeToggle.innerHTML = '<i data-lucide="moon" class="w-5 h-5"></i>';
localStorage.setItem('theme', 'dark');
} else {
themeToggle.innerHTML = '<i data-lucide="sun" class="w-5 h-5"></i>';
localStorage.setItem('theme', 'light');
}
// Reinitialize icons after DOM change
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
});
}
// Professional card hover animations
function initializeCardAnimations() {
document.querySelectorAll('.professional-card').forEach(card => {
card.addEventListener('mouseenter', (e) => {
const rect = card.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const mouseX = e.clientX;
const mouseY = e.clientY;
const deltaX = (mouseX - centerX) * 0.05;
const deltaY = (mouseY - centerY) * 0.05;
card.style.transform = `translateY(-4px) rotateX(${-deltaY}deg) rotateY(${deltaX}deg)`;
});
card.addEventListener('mouseleave', () => {
card.style.transform = 'translateY(0) rotateX(0deg) rotateY(0deg)';
});
});
}
// Intersection Observer for scroll animations
function initializeScrollAnimations() {
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);
// Apply scroll animations to cards
document.querySelectorAll('.professional-card').forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `opacity 0.6s ease ${index * 0.1}s, transform 0.6s ease ${index * 0.1}s`;
observer.observe(card);
});
// Apply scroll animations to support cards
document.querySelectorAll('.professional-support-card').forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `opacity 0.6s ease ${index * 0.15}s, transform 0.6s ease ${index * 0.15}s`;
observer.observe(card);
});
}
// Professional button interactions with enhanced effects
function initializeButtonEffects() {
// Add ripple animation keyframes to document
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: scale(3);
opacity: 0;
}
}
`;
document.head.appendChild(style);
// Add click ripple effect to buttons
document.querySelectorAll('.professional-btn-primary, .professional-btn-secondary, .professional-btn-urgent').forEach(btn => {
btn.addEventListener('click', (e) => {
createRippleEffect(btn, e);
});
});
}
// Create ripple effect for button clicks
function createRippleEffect(button, event) {
const ripple = document.createElement('div');
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left - size / 2;
const y = event.clientY - rect.top - size / 2;
ripple.style.cssText = `
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.4);
width: ${size}px;
height: ${size}px;
left: ${x}px;
top: ${y}px;
animation: ripple 0.5s linear;
pointer-events: none;
`;
button.style.position = 'relative';
button.style.overflow = 'hidden';
button.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 500);
}
// Subtle floating animation for hero background
function initializeHeroAnimations() {
const hero = document.querySelector('.professional-hero');
if (!hero) return;
let mouseX = 0;
let mouseY = 0;
hero.addEventListener('mousemove', (e) => {
const rect = hero.getBoundingClientRect();
mouseX = (e.clientX - rect.left) / rect.width;
mouseY = (e.clientY - rect.top) / rect.height;
const translateX = (mouseX - 0.5) * 10;
const translateY = (mouseY - 0.5) * 10;
hero.style.setProperty('--mouse-x', `${translateX}px`);
hero.style.setProperty('--mouse-y', `${translateY}px`);
});
}
// Enhanced smooth scrolling for anchor links
function initializeSmoothScrolling() {
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'
});
}
});
});
}
// WebP support detection
function initializeWebPSupport() {
function checkWebPSupport() {
const webP = new Image();
webP.onload = webP.onerror = function () {
if (webP.height === 2) {
document.documentElement.classList.add('webp');
}
};
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
}
checkWebPSupport();
}
// Utility function to reinitialize components (useful for dynamic content)
function reinitializeProfessionalTheme() {
initializeLucideIcons();
initializeCardAnimations();
initializeButtonEffects();
}
// Navigation dropdown functionality
function initializeNavigation() {
// Handle dropdown menus
document.querySelectorAll('.dropdown').forEach(dropdown => {
const button = dropdown.querySelector('[data-dropdown-toggle]');
const menu = dropdown.querySelector('.dropdown-menu');
if (button && menu) {
button.addEventListener('click', (e) => {
e.preventDefault();
menu.classList.toggle('show');
});
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
if (!dropdown.contains(e.target)) {
menu.classList.remove('show');
}
});
}
});
}
// Mobile menu functionality
function initializeMobileMenu() {
const mobileMenuButton = document.getElementById('mobile-menu-toggle');
const mobileMenu = document.getElementById('mobile-menu');
const menuIcon = document.getElementById('menu-icon');
const closeIcon = document.getElementById('close-icon');
if (mobileMenuButton && mobileMenu) {
mobileMenuButton.addEventListener('click', () => {
mobileMenu.classList.toggle('hidden');
menuIcon.classList.toggle('hidden');
closeIcon.classList.toggle('hidden');
mobileMenuButton.setAttribute('aria-expanded',
!mobileMenu.classList.contains('hidden') ? 'true' : 'false'
);
});
// Close mobile menu when clicking on a link
mobileMenu.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.add('hidden');
menuIcon.classList.remove('hidden');
closeIcon.classList.add('hidden');
mobileMenuButton.setAttribute('aria-expanded', 'false');
});
});
// Close mobile menu when clicking outside
document.addEventListener('click', (e) => {
if (!mobileMenuButton.contains(e.target) && !mobileMenu.contains(e.target)) {
mobileMenu.classList.add('hidden');
menuIcon.classList.remove('hidden');
closeIcon.classList.add('hidden');
mobileMenuButton.setAttribute('aria-expanded', 'false');
}
});
}
}
// Form enhancements
function initializeForms() {
// Add floating label effects
document.querySelectorAll('.form-floating input, .form-floating textarea').forEach(input => {
input.addEventListener('focus', () => {
input.parentElement.classList.add('focused');
});
input.addEventListener('blur', () => {
if (!input.value) {
input.parentElement.classList.remove('focused');
}
});
// Initialize state for pre-filled inputs
if (input.value) {
input.parentElement.classList.add('focused');
}
});
}
// Loading state management
function showLoading(element) {
if (!element) return;
element.classList.add('loading');
element.disabled = true;
const originalText = element.textContent;
element.setAttribute('data-original-text', originalText);
element.innerHTML = '<i data-lucide="loader-2" class="w-4 h-4 animate-spin mr-2"></i>Loading...';
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
}
function hideLoading(element) {
if (!element) return;
element.classList.remove('loading');
element.disabled = false;
const originalText = element.getAttribute('data-original-text');
if (originalText) {
element.textContent = originalText;
element.removeAttribute('data-original-text');
}
}
// Toast notification system
function showToast(message, type = 'info', duration = 5000) {
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.innerHTML = `
<div class="toast-content">
<i data-lucide="${getToastIcon(type)}" class="w-5 h-5"></i>
<span>${message}</span>
</div>
<button class="toast-close" onclick="this.parentElement.remove()">
<i data-lucide="x" class="w-4 h-4"></i>
</button>
`;
// Add toast container if it doesn't exist
let container = document.querySelector('.toast-container');
if (!container) {
container = document.createElement('div');
container.className = 'toast-container';
document.body.appendChild(container);
}
container.appendChild(toast);
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
// Auto remove after duration
setTimeout(() => {
toast.remove();
}, duration);
}
function getToastIcon(type) {
const icons = {
success: 'check-circle',
error: 'alert-circle',
warning: 'alert-triangle',
info: 'info'
};
return icons[type] || icons.info;
}
// Scroll-to-top functionality
function initializeScrollToTop() {
const scrollButton = document.createElement('button');
scrollButton.className = 'scroll-to-top professional-btn-primary';
scrollButton.innerHTML = '<i data-lucide="arrow-up" class="w-5 h-5"></i>';
scrollButton.setAttribute('aria-label', 'Scroll to top');
document.body.appendChild(scrollButton);
// Show/hide button based on scroll position
window.addEventListener('scroll', () => {
if (window.pageYOffset > 300) {
scrollButton.classList.add('show');
} else {
scrollButton.classList.remove('show');
}
});
// Scroll to top functionality
scrollButton.addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
}
// Export functions for global use
window.ProfessionalTheme = {
reinitialize: reinitializeProfessionalTheme,
showLoading: showLoading,
hideLoading: hideLoading,
showToast: showToast,
createRippleEffect: createRippleEffect
};