Initial AI-generated site
This commit is contained in:
+285
@@ -0,0 +1,285 @@
|
||||
<!doctype html>
|
||||
<html lang="he" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>מרכז האיקידו הישראלי | כפר סבא</title>
|
||||
<meta name="description" content="מתחם אימונים חדש לאיקידו בכפר סבא. למדו את אמנות ההגנה העצמית היפנית בסביבה מקצועית ותומכת.">
|
||||
<meta property="og:title" content="מרכז האיקידו הישראלי">
|
||||
<meta property="og:description" content="מתחם אימונים חדש לאיקידו בכפר סבא">
|
||||
<meta property="og:type" content="website">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><circle cx='50' cy='50' r='45' fill='none' stroke='%23000' stroke-width='3'/><path d='M50 15 L50 85 M25 50 Q50 30 75 50 Q50 70 25 50' fill='none' stroke='%23000' stroke-width='2'/></svg>">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@300;400;700;900&family=Frank+Ruhl+Libre:wght@400;700&family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<a href="#main-content" class="skip-link">דלג לתוכן הראשי</a>
|
||||
<div class="cursor-follower" aria-hidden="true"></div>
|
||||
|
||||
<nav class="main-nav" aria-label="ניווט ראשי">
|
||||
<div class="nav-inner">
|
||||
<a href="#hero" class="nav-logo">
|
||||
<svg viewBox="0 0 60 60" class="logo-mark" aria-hidden="true">
|
||||
<circle cx="30" cy="30" r="28" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
<path d="M30 8 L30 52" stroke="currentColor" stroke-width="1" class="logo-line"/>
|
||||
<path d="M12 30 Q30 18 48 30 Q30 42 12 30" fill="none" stroke="currentColor" stroke-width="1" class="logo-flow"/>
|
||||
</svg>
|
||||
<span>מרכז האיקידו</span>
|
||||
</a>
|
||||
<button class="nav-toggle" aria-label="תפריט ניווט" aria-expanded="false" aria-controls="nav-menu">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<ul class="nav-links" id="nav-menu">
|
||||
<li><a href="#about">אודות</a></li>
|
||||
<li><a href="#philosophy">הפילוסופיה</a></li>
|
||||
<li><a href="#schedule">לוח אימונים</a></li>
|
||||
<li><a href="#contact">צור קשר</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<header id="hero" class="hero">
|
||||
<div class="hero-bg">
|
||||
<svg class="enso" viewBox="0 0 400 400" aria-hidden="true">
|
||||
<circle cx="200" cy="200" r="150" fill="none" stroke="var(--ink)" stroke-width="2" class="enso-circle" pathLength="1"/>
|
||||
</svg>
|
||||
<div class="energy-lines" aria-hidden="true">
|
||||
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 50 Q25 30 50 50 T100 50" class="flow-line"/>
|
||||
<path d="M0 60 Q25 40 50 60 T100 60" class="flow-line"/>
|
||||
<path d="M0 40 Q25 20 50 40 T100 40" class="flow-line"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-content" id="main-content">
|
||||
<p class="hero-tag reveal">כפר סבא · מתחם חדש</p>
|
||||
<h1 class="hero-title reveal">
|
||||
<span class="title-main">מרכז האיקידו</span>
|
||||
<em>הישראלי</em>
|
||||
</h1>
|
||||
<p class="hero-subtitle reveal">אמנות התנועה וההרמוניה. דרך חדשה להכיר את עצמך.</p>
|
||||
<a href="#contact" class="cta-btn reveal">
|
||||
<span>התחילו לתרגל</span>
|
||||
<svg viewBox="0 0 24 24" class="cta-arrow" aria-hidden="true">
|
||||
<path d="M19 12H5M12 5l-7 7 7 7" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div class="scroll-hint" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 40">
|
||||
<rect x="6" y="1" width="12" height="22" rx="6" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
<circle cx="12" cy="10" r="2" fill="currentColor" class="scroll-dot"/>
|
||||
</svg>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section id="about" class="about">
|
||||
<div class="section-inner">
|
||||
<div class="about-visual">
|
||||
<div class="circle-composition">
|
||||
<svg viewBox="0 0 300 300" class="composition-svg" aria-hidden="true">
|
||||
<circle cx="150" cy="150" r="120" class="comp-circle c1"/>
|
||||
<circle cx="150" cy="150" r="80" class="comp-circle c2"/>
|
||||
<circle cx="150" cy="150" r="40" class="comp-circle c3"/>
|
||||
<path d="M150 30 L150 270" class="comp-line"/>
|
||||
<path d="M30 150 L270 150" class="comp-line"/>
|
||||
</svg>
|
||||
<div class="kanji-overlay" aria-hidden="true">合気道</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="about-text">
|
||||
<h2 class="section-title reveal">אודות המרכז</h2>
|
||||
<p class="lead reveal">מרכז האיקידו הישראלי בכפר סבא הוא מתחם אימונים חדש ומודרני, המציע חוויית לימוד ייחודית של אמנות הלחימה היפנית העתיקה.</p>
|
||||
<p class="reveal">האיקידו אינה רק שיטת הגנה עצמית — היא דרך חיים שלמה. אנו מאמינים בפיתוח הגוף והנפש יחד, תוך כיבוד העקרונות של הרמוניה, זרימה ושלום.</p>
|
||||
<p class="reveal">המרכז שלנו מציע סביבה בטוחה ותומכת למתאמנים מכל הרמות — ממתחילים לחלוטין ועד מתקדמים המבקשים להעמיק את הידע שלהם.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="philosophy" class="philosophy">
|
||||
<div class="section-inner">
|
||||
<h2 class="section-title section-title--center reveal">הפילוסופיה שלנו</h2>
|
||||
<div class="principles">
|
||||
<article class="principle principle--featured reveal">
|
||||
<div class="principle-icon">
|
||||
<svg viewBox="0 0 80 80" aria-hidden="true">
|
||||
<circle cx="40" cy="40" r="35" fill="none" stroke="currentColor" stroke-width="1"/>
|
||||
<circle cx="40" cy="25" r="8" fill="currentColor" class="breathing-dot"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>אי — <span lang="ja">合</span></h3>
|
||||
<p>התאמה והרמוניה. לא להתנגד לכוח, אלא להתמזג איתו ולהפנות אותו.</p>
|
||||
</article>
|
||||
<article class="principle reveal">
|
||||
<div class="principle-icon">
|
||||
<svg viewBox="0 0 80 80" aria-hidden="true">
|
||||
<path d="M10 40 Q40 10 70 40 Q40 70 10 40" fill="none" stroke="currentColor" stroke-width="1" class="wave-path"/>
|
||||
<circle cx="40" cy="40" r="5" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>קי — <span lang="ja">気</span></h3>
|
||||
<p>אנרגיית החיים. לחבר בין הנשימה, התנועה והכוונה לזרימה אחת.</p>
|
||||
</article>
|
||||
<article class="principle reveal">
|
||||
<div class="principle-icon">
|
||||
<svg viewBox="0 0 80 80" aria-hidden="true">
|
||||
<path d="M40 10 L40 70 M20 25 L40 10 L60 25" fill="none" stroke="currentColor" stroke-width="1"/>
|
||||
<circle cx="40" cy="55" r="12" fill="none" stroke="currentColor" stroke-width="1" class="rotating-circle"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3>דו — <span lang="ja">道</span></h3>
|
||||
<p>הדרך. מסע מתמשך של למידה, צמיחה והתפתחות אישית.</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="quote-section">
|
||||
<div class="section-inner">
|
||||
<figure class="main-quote reveal">
|
||||
<blockquote>
|
||||
<p>הניצחון האמיתי הוא ניצחון על עצמך</p>
|
||||
</blockquote>
|
||||
<figcaption>— מוריהיי אואשיבה, מייסד האיקידו</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="schedule" class="schedule">
|
||||
<div class="section-inner">
|
||||
<h2 class="section-title reveal">לוח אימונים</h2>
|
||||
<div class="schedule-grid">
|
||||
<div class="schedule-card reveal">
|
||||
<div class="card-header">
|
||||
<span class="day">ראשון</span>
|
||||
<span class="level level--beginner"><span class="level-icon" aria-hidden="true">●</span> מתחילים</span>
|
||||
</div>
|
||||
<div class="card-time"><span class="time-start">18:00</span> — <span class="time-end">19:30</span></div>
|
||||
<p class="card-desc">שיעור בסיסי — עקרונות יסוד ונפילות</p>
|
||||
</div>
|
||||
<div class="schedule-card reveal">
|
||||
<div class="card-header">
|
||||
<span class="day">שלישי</span>
|
||||
<span class="level level--all"><span class="level-icon" aria-hidden="true">◐</span> כל הרמות</span>
|
||||
</div>
|
||||
<div class="card-time"><span class="time-start">19:00</span> — <span class="time-end">20:30</span></div>
|
||||
<p class="card-desc">אימון משולב — טכניקות וזרימה</p>
|
||||
</div>
|
||||
<div class="schedule-card reveal">
|
||||
<div class="card-header">
|
||||
<span class="day">חמישי</span>
|
||||
<span class="level level--advanced"><span class="level-icon" aria-hidden="true">◆</span> מתקדמים</span>
|
||||
</div>
|
||||
<div class="card-time"><span class="time-start">19:00</span> — <span class="time-end">21:00</span></div>
|
||||
<p class="card-desc">אימון עומק — רנדורי ויישומים</p>
|
||||
</div>
|
||||
<div class="schedule-card reveal">
|
||||
<div class="card-header">
|
||||
<span class="day">שבת</span>
|
||||
<span class="level level--all"><span class="level-icon" aria-hidden="true">◐</span> כל הרמות</span>
|
||||
</div>
|
||||
<div class="card-time"><span class="time-start">09:00</span> — <span class="time-end">11:00</span></div>
|
||||
<p class="card-desc">אימון בוקר — נשימה, מדיטציה ותרגול</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="schedule-note reveal">שיעור ניסיון ראשון ללא תשלום · יש להירשם מראש</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="contact" class="contact">
|
||||
<div class="section-inner">
|
||||
<div class="contact-content">
|
||||
<h2 class="section-title reveal">בואו להתאמן</h2>
|
||||
<p class="reveal">המרכז ממוקם בכפר סבא, בסביבה נעימה ונגישה. מוזמנים ליצור קשר לפרטים נוספים או להגיע לשיעור ניסיון.</p>
|
||||
<address class="contact-info reveal">
|
||||
<div class="info-item">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
<circle cx="12" cy="10" r="3" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
<span>כפר סבא <em class="placeholder">[הכתובת תעודכן בקרוב]</em></span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72 12.84 12.84 0 00.7 2.81 2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45 12.84 12.84 0 002.81.7A2 2 0 0122 16.92z" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
<span class="placeholder">[טלפון יעודכן בקרוב]</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
<path d="M22 6l-10 7L2 6" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
<span class="placeholder">[דוא״ל יעודכן בקרוב]</span>
|
||||
</div>
|
||||
</address>
|
||||
<form class="contact-form" id="contact-form" novalidate>
|
||||
<div class="form-group reveal">
|
||||
<label for="name">שם מלא <span class="required" aria-hidden="true">*</span></label>
|
||||
<input type="text" id="name" name="name" autocomplete="name" required aria-required="true">
|
||||
<span class="error-message" role="alert"></span>
|
||||
</div>
|
||||
<div class="form-group reveal">
|
||||
<label for="phone">טלפון</label>
|
||||
<input type="tel" id="phone" name="phone" autocomplete="tel">
|
||||
</div>
|
||||
<div class="form-group reveal">
|
||||
<label for="email">דוא״ל <span class="required" aria-hidden="true">*</span></label>
|
||||
<input type="email" id="email" name="email" autocomplete="email" required aria-required="true">
|
||||
<span class="error-message" role="alert"></span>
|
||||
</div>
|
||||
<div class="form-group reveal">
|
||||
<label for="message">הודעה</label>
|
||||
<textarea id="message" name="message" rows="4"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="submit-btn reveal">
|
||||
<span>שליחה</span>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" fill="none" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="form-status" role="status" aria-live="polite"></div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="contact-visual">
|
||||
<svg viewBox="0 0 400 400" class="contact-art" aria-hidden="true">
|
||||
<defs>
|
||||
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:var(--accent);stop-opacity:0.3"/>
|
||||
<stop offset="100%" style="stop-color:var(--ink);stop-opacity:0.1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="200" cy="200" r="180" fill="url(#grad)"/>
|
||||
<circle cx="200" cy="200" r="140" fill="none" stroke="var(--ink)" stroke-width="0.5" class="orbit o1"/>
|
||||
<circle cx="200" cy="200" r="100" fill="none" stroke="var(--ink)" stroke-width="0.5" class="orbit o2"/>
|
||||
<circle cx="200" cy="200" r="60" fill="none" stroke="var(--ink)" stroke-width="0.5" class="orbit o3"/>
|
||||
<circle cx="200" cy="60" r="8" fill="var(--accent)" class="orbiting-dot d1"/>
|
||||
<circle cx="300" cy="200" r="6" fill="var(--ink)" class="orbiting-dot d2"/>
|
||||
<circle cx="200" cy="260" r="4" fill="var(--accent)" class="orbiting-dot d3"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="main-footer">
|
||||
<div class="footer-inner">
|
||||
<div class="footer-brand">
|
||||
<svg viewBox="0 0 60 60" class="footer-logo" aria-hidden="true">
|
||||
<circle cx="30" cy="30" r="28" fill="none" stroke="currentColor" stroke-width="1"/>
|
||||
<path d="M30 8 L30 52" stroke="currentColor" stroke-width="0.75"/>
|
||||
<path d="M12 30 Q30 18 48 30 Q30 42 12 30" fill="none" stroke="currentColor" stroke-width="0.75"/>
|
||||
</svg>
|
||||
<span>מרכז האיקידו הישראלי</span>
|
||||
</div>
|
||||
<p class="footer-copy">© <span id="current-year">2024</span> כל הזכויות שמורות</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,266 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
// Update year in footer
|
||||
const yearEl = document.getElementById('current-year');
|
||||
if (yearEl) {
|
||||
yearEl.textContent = new Date().getFullYear();
|
||||
}
|
||||
|
||||
// Custom cursor
|
||||
const cursor = document.querySelector('.cursor-follower');
|
||||
let mouseX = 0, mouseY = 0;
|
||||
let cursorX = 0, cursorY = 0;
|
||||
let cursorVisible = false;
|
||||
let animationFrameId = null;
|
||||
|
||||
if (cursor && !prefersReducedMotion && window.matchMedia('(pointer: fine)').matches) {
|
||||
function startCursorAnimation() {
|
||||
if (animationFrameId) return;
|
||||
animateCursor();
|
||||
}
|
||||
|
||||
function stopCursorAnimation() {
|
||||
if (animationFrameId) {
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
animationFrameId = null;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
mouseX = e.clientX;
|
||||
mouseY = e.clientY;
|
||||
if (!cursorVisible) {
|
||||
cursorVisible = true;
|
||||
cursor.classList.add('active');
|
||||
startCursorAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseleave', () => {
|
||||
cursorVisible = false;
|
||||
cursor.classList.remove('active');
|
||||
stopCursorAnimation();
|
||||
});
|
||||
|
||||
const interactiveElements = document.querySelectorAll('a, button, input, textarea, [tabindex]');
|
||||
interactiveElements.forEach(el => {
|
||||
el.addEventListener('mouseenter', () => cursor.classList.add('hover'));
|
||||
el.addEventListener('mouseleave', () => cursor.classList.remove('hover'));
|
||||
});
|
||||
|
||||
function animateCursor() {
|
||||
const ease = 0.15;
|
||||
cursorX += (mouseX - cursorX) * ease;
|
||||
cursorY += (mouseY - cursorY) * ease;
|
||||
cursor.style.left = cursorX + 'px';
|
||||
cursor.style.top = cursorY + 'px';
|
||||
if (cursorVisible) {
|
||||
animationFrameId = requestAnimationFrame(animateCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation scroll effect
|
||||
const nav = document.querySelector('.main-nav');
|
||||
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 50) {
|
||||
nav.classList.add('scrolled');
|
||||
} else {
|
||||
nav.classList.remove('scrolled');
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
// Mobile navigation toggle
|
||||
const navToggle = document.querySelector('.nav-toggle');
|
||||
const navLinks = document.querySelector('.nav-links');
|
||||
|
||||
if (navToggle && navLinks) {
|
||||
navToggle.addEventListener('click', () => {
|
||||
const isOpen = navToggle.getAttribute('aria-expanded') === 'true';
|
||||
navToggle.setAttribute('aria-expanded', !isOpen);
|
||||
navLinks.classList.toggle('open');
|
||||
document.body.style.overflow = isOpen ? '' : 'hidden';
|
||||
});
|
||||
|
||||
navLinks.querySelectorAll('a').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
navToggle.setAttribute('aria-expanded', 'false');
|
||||
navLinks.classList.remove('open');
|
||||
document.body.style.overflow = '';
|
||||
});
|
||||
});
|
||||
|
||||
// Close on escape
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && navLinks.classList.contains('open')) {
|
||||
navToggle.setAttribute('aria-expanded', 'false');
|
||||
navLinks.classList.remove('open');
|
||||
document.body.style.overflow = '';
|
||||
navToggle.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Reveal animations with Intersection Observer
|
||||
if (!prefersReducedMotion) {
|
||||
const reveals = document.querySelectorAll('.reveal');
|
||||
let revealDelay = 0;
|
||||
|
||||
const revealObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setTimeout(() => {
|
||||
entry.target.classList.add('visible');
|
||||
}, revealDelay);
|
||||
revealDelay += 80;
|
||||
setTimeout(() => { revealDelay = 0; }, 500);
|
||||
revealObserver.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
});
|
||||
|
||||
reveals.forEach(el => revealObserver.observe(el));
|
||||
} else {
|
||||
document.querySelectorAll('.reveal').forEach(el => {
|
||||
el.classList.add('visible');
|
||||
});
|
||||
}
|
||||
|
||||
// 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 offsetTop = target.offsetTop - 80;
|
||||
window.scrollTo({
|
||||
top: offsetTop,
|
||||
behavior: prefersReducedMotion ? 'auto' : 'smooth'
|
||||
});
|
||||
// Move focus to target for accessibility
|
||||
target.setAttribute('tabindex', '-1');
|
||||
target.focus({ preventScroll: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Form handling with validation
|
||||
const contactForm = document.getElementById('contact-form');
|
||||
if (contactForm) {
|
||||
const nameInput = contactForm.querySelector('#name');
|
||||
const emailInput = contactForm.querySelector('#email');
|
||||
|
||||
function validateField(input, errorEl) {
|
||||
let isValid = true;
|
||||
let message = '';
|
||||
|
||||
if (input.required && !input.value.trim()) {
|
||||
isValid = false;
|
||||
message = 'שדה חובה';
|
||||
} else if (input.type === 'email' && input.value) {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(input.value)) {
|
||||
isValid = false;
|
||||
message = 'כתובת דוא״ל לא תקינה';
|
||||
}
|
||||
}
|
||||
|
||||
if (errorEl) {
|
||||
errorEl.textContent = message;
|
||||
}
|
||||
input.classList.toggle('error', !isValid);
|
||||
return isValid;
|
||||
}
|
||||
|
||||
[nameInput, emailInput].forEach(input => {
|
||||
if (input) {
|
||||
const errorEl = input.parentElement.querySelector('.error-message');
|
||||
input.addEventListener('blur', () => validateField(input, errorEl));
|
||||
input.addEventListener('input', () => {
|
||||
if (input.classList.contains('error')) {
|
||||
validateField(input, errorEl);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
contactForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const nameError = nameInput.parentElement.querySelector('.error-message');
|
||||
const emailError = emailInput.parentElement.querySelector('.error-message');
|
||||
|
||||
const nameValid = validateField(nameInput, nameError);
|
||||
const emailValid = validateField(emailInput, emailError);
|
||||
|
||||
if (!nameValid || !emailValid) {
|
||||
const firstInvalid = contactForm.querySelector('.error');
|
||||
if (firstInvalid) firstInvalid.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = this.querySelector('.submit-btn');
|
||||
const btnText = btn.querySelector('span');
|
||||
const status = this.querySelector('.form-status');
|
||||
const originalText = btnText.textContent;
|
||||
|
||||
btnText.textContent = 'שולח...';
|
||||
btn.disabled = true;
|
||||
|
||||
// Simulate submission
|
||||
setTimeout(() => {
|
||||
btnText.textContent = 'נשלח בהצלחה!';
|
||||
btn.classList.add('success');
|
||||
status.textContent = 'תודה! נחזור אליכם בהקדם.';
|
||||
|
||||
setTimeout(() => {
|
||||
btnText.textContent = originalText;
|
||||
btn.classList.remove('success');
|
||||
btn.disabled = false;
|
||||
status.textContent = '';
|
||||
contactForm.reset();
|
||||
// Clear any error states
|
||||
contactForm.querySelectorAll('.error').forEach(el => el.classList.remove('error'));
|
||||
contactForm.querySelectorAll('.error-message').forEach(el => el.textContent = '');
|
||||
}, 3000);
|
||||
}, 1500);
|
||||
});
|
||||
}
|
||||
|
||||
// Kanji rotation on scroll (only if motion is allowed)
|
||||
if (!prefersReducedMotion) {
|
||||
const kanji = document.querySelector('.kanji-overlay');
|
||||
const aboutSection = document.querySelector('.about');
|
||||
|
||||
if (kanji && aboutSection) {
|
||||
const kanjiObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
window.addEventListener('scroll', handleKanjiScroll, { passive: true });
|
||||
} else {
|
||||
window.removeEventListener('scroll', handleKanjiScroll);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0 });
|
||||
|
||||
function handleKanjiScroll() {
|
||||
const rect = aboutSection.getBoundingClientRect();
|
||||
const progress = 1 - (rect.bottom / (window.innerHeight + rect.height));
|
||||
const rotation = Math.max(0, Math.min(progress * 10, 10));
|
||||
const isRTL = document.documentElement.dir === 'rtl';
|
||||
const translateX = isRTL ? '50%' : '-50%';
|
||||
kanji.style.transform = `translate(${translateX}, -50%) rotate(${rotation}deg)`;
|
||||
}
|
||||
|
||||
kanjiObserver.observe(aboutSection);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user