Add CSS, JS and asset files (without videos)
Dieser Commit ist enthalten in:
499
js/components.js
Normale Datei
499
js/components.js
Normale Datei
@ -0,0 +1,499 @@
|
||||
/**
|
||||
* UI Components module for IntelSight website
|
||||
* Contains all interactive UI component logic
|
||||
*/
|
||||
|
||||
// Language Toggle Component
|
||||
const LanguageToggle = {
|
||||
element: null,
|
||||
|
||||
/**
|
||||
* Initialize language toggle
|
||||
*/
|
||||
init() {
|
||||
this.element = document.querySelector(SELECTORS.LANG_TOGGLE);
|
||||
if (!this.element) return;
|
||||
|
||||
this.element.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.toggle();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle between languages
|
||||
*/
|
||||
toggle() {
|
||||
const newLanguage = getCurrentLanguage() === 'de' ? 'en' : 'de';
|
||||
switchLanguage(newLanguage);
|
||||
|
||||
// Update expand button text after language change
|
||||
ProductShowcase.updateExpandButtonText();
|
||||
}
|
||||
};
|
||||
|
||||
// Navigation Component
|
||||
const Navigation = {
|
||||
navbar: null,
|
||||
|
||||
/**
|
||||
* Initialize navigation component
|
||||
*/
|
||||
init() {
|
||||
this.navbar = document.querySelector(SELECTORS.NAVBAR);
|
||||
this.setupSmoothScrolling();
|
||||
this.setupMobileMenu();
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup smooth scrolling for anchor links
|
||||
*/
|
||||
setupSmoothScrolling() {
|
||||
document.querySelectorAll(SELECTORS.SMOOTH_LINKS).forEach(anchor => {
|
||||
anchor.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const targetId = this.getAttribute('href');
|
||||
const target = document.querySelector(targetId);
|
||||
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup mobile menu functionality
|
||||
*/
|
||||
setupMobileMenu() {
|
||||
// Mobile menu logic would go here if needed
|
||||
// Currently not implemented as per YAGNI principle
|
||||
}
|
||||
};
|
||||
|
||||
// About Section Tabs
|
||||
const AboutTabs = {
|
||||
tabs: null,
|
||||
panels: null,
|
||||
|
||||
/**
|
||||
* Initialize about section tabs
|
||||
*/
|
||||
init() {
|
||||
this.tabs = document.querySelectorAll(SELECTORS.ABOUT_TABS);
|
||||
this.panels = document.querySelectorAll(SELECTORS.ABOUT_PANELS);
|
||||
|
||||
if (!this.tabs.length) return;
|
||||
|
||||
this.tabs.forEach(tab => {
|
||||
tab.addEventListener('click', () => this.switchTab(tab));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Switch to selected tab
|
||||
* @param {HTMLElement} selectedTab - Tab element that was clicked
|
||||
*/
|
||||
switchTab(selectedTab) {
|
||||
const targetPanelId = selectedTab.getAttribute(DATA_ATTRS.TAB);
|
||||
|
||||
// Remove active class from all tabs and panels
|
||||
this.tabs.forEach(tab => tab.classList.remove(CLASSES.ACTIVE));
|
||||
this.panels.forEach(panel => panel.classList.remove(CLASSES.ACTIVE));
|
||||
|
||||
// Add active class to selected tab and corresponding panel
|
||||
selectedTab.classList.add(CLASSES.ACTIVE);
|
||||
const targetPanel = document.getElementById(targetPanelId);
|
||||
if (targetPanel) {
|
||||
targetPanel.classList.add(CLASSES.ACTIVE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Product Showcase Component
|
||||
const ProductShowcase = {
|
||||
expandButton: null,
|
||||
toolsGrid: null,
|
||||
|
||||
/**
|
||||
* Initialize product showcase
|
||||
*/
|
||||
init() {
|
||||
this.expandButton = document.querySelector(SELECTORS.EXPAND_BUTTON);
|
||||
this.toolsGrid = document.querySelector(SELECTORS.TOOLS_GRID);
|
||||
|
||||
if (!this.expandButton || !this.toolsGrid) return;
|
||||
|
||||
this.expandButton.addEventListener('click', () => this.toggleExpand());
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle expand/collapse state
|
||||
*/
|
||||
toggleExpand() {
|
||||
const isExpanded = this.expandButton.getAttribute(DATA_ATTRS.EXPANDED) === 'true';
|
||||
|
||||
if (isExpanded) {
|
||||
this.collapse();
|
||||
} else {
|
||||
this.expand();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Expand the tools grid
|
||||
*/
|
||||
expand() {
|
||||
this.toolsGrid.classList.remove(CLASSES.COLLAPSED);
|
||||
this.expandButton.setAttribute(DATA_ATTRS.EXPANDED, 'true');
|
||||
this.updateExpandButtonText();
|
||||
},
|
||||
|
||||
/**
|
||||
* Collapse the tools grid
|
||||
*/
|
||||
collapse() {
|
||||
this.toolsGrid.classList.add(CLASSES.COLLAPSED);
|
||||
this.expandButton.setAttribute(DATA_ATTRS.EXPANDED, 'false');
|
||||
this.updateExpandButtonText();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update expand button text based on state
|
||||
*/
|
||||
updateExpandButtonText() {
|
||||
const expandText = this.expandButton?.querySelector('.expand-text');
|
||||
if (!expandText) return;
|
||||
|
||||
const isExpanded = this.expandButton.getAttribute(DATA_ATTRS.EXPANDED) === 'true';
|
||||
expandText.textContent = getTranslation(isExpanded ? 'hideDetails' : 'expandDetails');
|
||||
}
|
||||
};
|
||||
|
||||
// Login Modal Component
|
||||
const LoginModal = {
|
||||
modalElement: null,
|
||||
modalStyles: null,
|
||||
|
||||
/**
|
||||
* Show login modal
|
||||
*/
|
||||
show() {
|
||||
this.createModal();
|
||||
this.attachEventListeners();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create modal HTML and styles
|
||||
*/
|
||||
createModal() {
|
||||
// Create modal element
|
||||
this.modalElement = document.createElement('div');
|
||||
this.modalElement.className = 'login-modal';
|
||||
this.modalElement.innerHTML = this.getModalHTML();
|
||||
document.body.appendChild(this.modalElement);
|
||||
|
||||
// Add modal styles if not already added
|
||||
if (!this.modalStyles) {
|
||||
this.addModalStyles();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get modal HTML content
|
||||
* @returns {string} Modal HTML
|
||||
*/
|
||||
getModalHTML() {
|
||||
const t = getTranslation;
|
||||
return `
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<div class="modal-header">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="lock-icon">
|
||||
<rect x="5" y="11" width="14" height="10" rx="2" stroke="currentColor" stroke-width="2"/>
|
||||
<path d="M7 11V7C7 4.23858 9.23858 2 12 2C14.7614 2 17 4.23858 17 7V11" stroke="currentColor" stroke-width="2"/>
|
||||
<circle cx="12" cy="16" r="1" fill="currentColor"/>
|
||||
</svg>
|
||||
<h3>${t('authRequired')}</h3>
|
||||
</div>
|
||||
<p>${t('authDescription')}</p>
|
||||
<form id="loginForm">
|
||||
<div class="form-group">
|
||||
<label for="auth-password">${t('accessCode')}</label>
|
||||
<input type="password" id="auth-password" placeholder="${t('accessCodePlaceholder')}" required autofocus>
|
||||
</div>
|
||||
<button type="submit" class="primary-button">${t('grantAccess')}</button>
|
||||
</form>
|
||||
<p class="auth-note">${t('noAccess')} <a href="mailto:info@intelsight.de">${t('contactUs')}</a></p>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add modal styles to document
|
||||
*/
|
||||
addModalStyles() {
|
||||
this.modalStyles = document.createElement('style');
|
||||
this.modalStyles.textContent = `
|
||||
.login-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10000;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
.modal-content {
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
padding: 2.5rem;
|
||||
max-width: 400px;
|
||||
width: 90%;
|
||||
position: relative;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.modal-header {
|
||||
text-align: center;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.modal-header .lock-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
color: #0066cc;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #666;
|
||||
font-size: 2rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.modal-close:hover {
|
||||
background: #f0f0f0;
|
||||
color: #333;
|
||||
}
|
||||
.modal-content h3 {
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.modal-content p {
|
||||
color: #666;
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
.modal-content .form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.modal-content label {
|
||||
display: block;
|
||||
color: #333;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.modal-content input {
|
||||
width: 100%;
|
||||
padding: 0.875rem;
|
||||
background: #f8f8f8;
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
color: #333;
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.modal-content input:focus {
|
||||
outline: none;
|
||||
border-color: #0066cc;
|
||||
background: #fff;
|
||||
}
|
||||
.modal-content input::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
.modal-content .primary-button {
|
||||
width: 100%;
|
||||
padding: 0.875rem;
|
||||
background: #0066cc;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.modal-content .primary-button:hover {
|
||||
background: #0052a3;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0, 102, 204, 0.3);
|
||||
}
|
||||
.auth-note {
|
||||
text-align: center;
|
||||
margin-top: 1.5rem;
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
}
|
||||
.auth-note a {
|
||||
color: #0066cc;
|
||||
text-decoration: none;
|
||||
}
|
||||
.auth-note a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(this.modalStyles);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach event listeners to modal
|
||||
*/
|
||||
attachEventListeners() {
|
||||
// Close button
|
||||
const closeBtn = this.modalElement.querySelector('.modal-close');
|
||||
closeBtn.addEventListener('click', () => this.close());
|
||||
|
||||
// Form submission
|
||||
const form = this.modalElement.querySelector('#loginForm');
|
||||
form.addEventListener('submit', (e) => this.handleSubmit(e));
|
||||
|
||||
// Click outside to close
|
||||
this.modalElement.addEventListener('click', (e) => {
|
||||
if (e.target === this.modalElement) {
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle form submission
|
||||
* @param {Event} e - Submit event
|
||||
*/
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
const password = document.getElementById('auth-password').value;
|
||||
|
||||
// Check password (temporarily hardcoded as requested)
|
||||
if (password === '123456') {
|
||||
sessionStorage.setItem(CONFIG.AUTH.SESSION_KEY, 'true');
|
||||
this.close();
|
||||
window.location.href = CONFIG.AUTH.REDIRECT_PAGE;
|
||||
} else {
|
||||
alert(getTranslation('wrongCode'));
|
||||
document.getElementById('auth-password').value = '';
|
||||
document.getElementById('auth-password').focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Close and remove modal
|
||||
*/
|
||||
close() {
|
||||
if (this.modalElement) {
|
||||
this.modalElement.remove();
|
||||
this.modalElement = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Contact Form Component
|
||||
const ContactForm = {
|
||||
form: null,
|
||||
|
||||
/**
|
||||
* Initialize contact form
|
||||
*/
|
||||
init() {
|
||||
this.form = document.querySelector(SELECTORS.CONTACT_FORM);
|
||||
if (!this.form) return;
|
||||
|
||||
this.form.addEventListener('submit', (e) => this.handleSubmit(e));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle form submission
|
||||
* @param {Event} e - Submit event
|
||||
*/
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get form data
|
||||
const formData = new FormData(this.form);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
// In production, this would send data to server
|
||||
console.log('Form submission:', data);
|
||||
|
||||
// Show success message
|
||||
alert(getTranslation('contactFormSuccess'));
|
||||
this.form.reset();
|
||||
}
|
||||
};
|
||||
|
||||
// Demo Request Handler
|
||||
const DemoRequest = {
|
||||
/**
|
||||
* Initialize demo request buttons
|
||||
*/
|
||||
init() {
|
||||
document.querySelectorAll('.primary-button, .secondary-button, .cta-button').forEach(button => {
|
||||
if (button.textContent.toLowerCase().includes('demo')) {
|
||||
button.addEventListener('click', (e) => this.handleDemoRequest(e));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle demo request
|
||||
* @param {Event} e - Click event
|
||||
*/
|
||||
handleDemoRequest(e) {
|
||||
e.preventDefault();
|
||||
alert(getTranslation('demoRequestAlert'));
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize all components
|
||||
const Components = {
|
||||
/**
|
||||
* Initialize all UI components
|
||||
*/
|
||||
init() {
|
||||
LanguageToggle.init();
|
||||
Navigation.init();
|
||||
AboutTabs.init();
|
||||
ProductShowcase.init();
|
||||
ContactForm.init();
|
||||
DemoRequest.init();
|
||||
}
|
||||
};
|
||||
|
||||
// Make showLoginModal globally available for onclick attribute
|
||||
window.showLoginModal = function() {
|
||||
LoginModal.show();
|
||||
};
|
||||
|
||||
// Make closeLoginModal globally available for onclick attribute
|
||||
window.closeLoginModal = function() {
|
||||
LoginModal.close();
|
||||
};
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren