941 lines
34 KiB
HTML
941 lines
34 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Glass Morphism Form Wizard - UI Hybrid 13</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #4facfe 75%, #00f2fe 100%);
|
|
background-size: 400% 400%;
|
|
animation: gradientShift 20s ease infinite;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 20px;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
@keyframes gradientShift {
|
|
0% { background-position: 0% 50%; }
|
|
50% { background-position: 100% 50%; }
|
|
100% { background-position: 0% 50%; }
|
|
}
|
|
|
|
/* Floating Glass Orbs */
|
|
.glass-orb {
|
|
position: fixed;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 50%;
|
|
animation: float 20s infinite ease-in-out;
|
|
}
|
|
|
|
.orb1 {
|
|
width: 200px;
|
|
height: 200px;
|
|
top: 10%;
|
|
left: 10%;
|
|
animation-delay: 0s;
|
|
}
|
|
|
|
.orb2 {
|
|
width: 150px;
|
|
height: 150px;
|
|
top: 70%;
|
|
right: 10%;
|
|
animation-delay: -5s;
|
|
}
|
|
|
|
.orb3 {
|
|
width: 100px;
|
|
height: 100px;
|
|
bottom: 20%;
|
|
left: 50%;
|
|
animation-delay: -10s;
|
|
}
|
|
|
|
@keyframes float {
|
|
0%, 100% { transform: translate(0, 0) rotate(0deg); }
|
|
25% { transform: translate(50px, -50px) rotate(90deg); }
|
|
50% { transform: translate(-50px, 50px) rotate(180deg); }
|
|
75% { transform: translate(30px, 30px) rotate(270deg); }
|
|
}
|
|
|
|
/* Main Wizard Container */
|
|
.wizard-container {
|
|
width: 100%;
|
|
max-width: 800px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(20px);
|
|
border-radius: 30px;
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
box-shadow:
|
|
0 20px 50px rgba(0, 0, 0, 0.1),
|
|
inset 0 0 0 1px rgba(255, 255, 255, 0.1);
|
|
overflow: hidden;
|
|
position: relative;
|
|
z-index: 10;
|
|
}
|
|
|
|
/* Progress Header */
|
|
.progress-header {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
backdrop-filter: blur(10px);
|
|
padding: 30px;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.step-indicators {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
position: relative;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.step-indicator {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.step-number {
|
|
width: 50px;
|
|
height: 50px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-weight: 600;
|
|
transition: all 0.3s ease;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.step-number::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: -2px;
|
|
background: linear-gradient(45deg, #667eea, #f093fb);
|
|
border-radius: 50%;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
z-index: -1;
|
|
}
|
|
|
|
.step-indicator.active .step-number::before,
|
|
.step-indicator.completed .step-number::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
.step-indicator.completed .step-number {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.step-label {
|
|
margin-top: 10px;
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-size: 14px;
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
.step-indicator.active .step-label,
|
|
.step-indicator.completed .step-label {
|
|
color: white;
|
|
}
|
|
|
|
/* Progress Line */
|
|
.progress-line {
|
|
position: absolute;
|
|
top: 25px;
|
|
left: 0;
|
|
right: 0;
|
|
height: 2px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
z-index: 1;
|
|
}
|
|
|
|
.progress-line-fill {
|
|
height: 100%;
|
|
background: linear-gradient(90deg, #667eea, #f093fb);
|
|
width: 0%;
|
|
transition: width 0.5s ease;
|
|
box-shadow: 0 0 20px rgba(102, 126, 234, 0.5);
|
|
}
|
|
|
|
/* Form Content */
|
|
.form-content {
|
|
padding: 40px;
|
|
min-height: 400px;
|
|
position: relative;
|
|
}
|
|
|
|
.form-step {
|
|
display: none;
|
|
animation: slideIn 0.5s ease;
|
|
}
|
|
|
|
.form-step.active {
|
|
display: block;
|
|
}
|
|
|
|
@keyframes slideIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(30px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
/* Glass Form Elements */
|
|
.form-group {
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
color: white;
|
|
font-weight: 500;
|
|
margin-bottom: 10px;
|
|
font-size: 14px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
.form-input,
|
|
.form-select,
|
|
.form-textarea {
|
|
width: 100%;
|
|
padding: 15px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
border-radius: 15px;
|
|
color: white;
|
|
font-size: 16px;
|
|
transition: all 0.3s ease;
|
|
outline: none;
|
|
}
|
|
|
|
.form-input::placeholder,
|
|
.form-textarea::placeholder {
|
|
color: rgba(255, 255, 255, 0.5);
|
|
}
|
|
|
|
.form-input:focus,
|
|
.form-select:focus,
|
|
.form-textarea:focus {
|
|
background: rgba(255, 255, 255, 0.15);
|
|
border-color: rgba(255, 255, 255, 0.4);
|
|
box-shadow: 0 0 30px rgba(102, 126, 234, 0.3);
|
|
}
|
|
|
|
.form-select option {
|
|
background: #2d3748;
|
|
color: white;
|
|
}
|
|
|
|
/* Validation States */
|
|
.form-group.error .form-input,
|
|
.form-group.error .form-select,
|
|
.form-group.error .form-textarea {
|
|
border-color: rgba(239, 68, 68, 0.5);
|
|
box-shadow: 0 0 20px rgba(239, 68, 68, 0.2);
|
|
}
|
|
|
|
.form-group.success .form-input,
|
|
.form-group.success .form-select,
|
|
.form-group.success .form-textarea {
|
|
border-color: rgba(16, 185, 129, 0.5);
|
|
box-shadow: 0 0 20px rgba(16, 185, 129, 0.2);
|
|
}
|
|
|
|
.error-message {
|
|
margin-top: 5px;
|
|
color: #ef4444;
|
|
font-size: 13px;
|
|
display: none;
|
|
}
|
|
|
|
.form-group.error .error-message {
|
|
display: block;
|
|
animation: shake 0.5s ease;
|
|
}
|
|
|
|
@keyframes shake {
|
|
0%, 100% { transform: translateX(0); }
|
|
25% { transform: translateX(-10px); }
|
|
75% { transform: translateX(10px); }
|
|
}
|
|
|
|
/* Checkbox and Radio Glass Style */
|
|
.checkbox-group,
|
|
.radio-group {
|
|
display: flex;
|
|
gap: 20px;
|
|
flex-wrap: wrap;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.checkbox-label,
|
|
.radio-label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: white;
|
|
cursor: pointer;
|
|
padding: 10px 20px;
|
|
background: rgba(255, 255, 255, 0.05);
|
|
border-radius: 10px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.checkbox-label:hover,
|
|
.radio-label:hover {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.checkbox-input,
|
|
.radio-input {
|
|
width: 20px;
|
|
height: 20px;
|
|
cursor: pointer;
|
|
accent-color: #667eea;
|
|
}
|
|
|
|
/* Navigation Buttons */
|
|
.form-navigation {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 30px;
|
|
background: rgba(255, 255, 255, 0.05);
|
|
backdrop-filter: blur(10px);
|
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.btn {
|
|
padding: 12px 30px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
border-radius: 50px;
|
|
color: white;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
font-size: 14px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.btn::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(45deg, #667eea, #f093fb);
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
z-index: -1;
|
|
}
|
|
|
|
.btn:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.btn:hover::before {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.btn:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: linear-gradient(45deg, #667eea, #f093fb);
|
|
border: none;
|
|
}
|
|
|
|
/* Save Progress */
|
|
.save-indicator {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.save-icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 2px solid rgba(255, 255, 255, 0.5);
|
|
border-radius: 50%;
|
|
border-top-color: transparent;
|
|
animation: spin 1s linear infinite;
|
|
display: none;
|
|
}
|
|
|
|
.save-indicator.saving .save-icon {
|
|
display: block;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* Summary Step */
|
|
.summary-content {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 20px;
|
|
padding: 30px;
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.summary-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 15px 0;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.summary-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.summary-label {
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.summary-value {
|
|
color: white;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* Success Animation */
|
|
.success-animation {
|
|
display: none;
|
|
text-align: center;
|
|
padding: 60px;
|
|
}
|
|
|
|
.success-icon {
|
|
width: 100px;
|
|
height: 100px;
|
|
margin: 0 auto 30px;
|
|
background: linear-gradient(45deg, #10b981, #34d399);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 50px;
|
|
color: white;
|
|
animation: successPulse 1s ease;
|
|
}
|
|
|
|
@keyframes successPulse {
|
|
0% { transform: scale(0); opacity: 0; }
|
|
50% { transform: scale(1.2); }
|
|
100% { transform: scale(1); opacity: 1; }
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 640px) {
|
|
.step-label {
|
|
display: none;
|
|
}
|
|
|
|
.form-navigation {
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
|
|
.btn {
|
|
width: 100%;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Floating Glass Orbs -->
|
|
<div class="glass-orb orb1"></div>
|
|
<div class="glass-orb orb2"></div>
|
|
<div class="glass-orb orb3"></div>
|
|
|
|
<!-- Wizard Container -->
|
|
<div class="wizard-container">
|
|
<!-- Progress Header -->
|
|
<div class="progress-header">
|
|
<div class="step-indicators">
|
|
<div class="step-indicator active" data-step="1">
|
|
<div class="step-number">1</div>
|
|
<div class="step-label">Personal Info</div>
|
|
</div>
|
|
<div class="step-indicator" data-step="2">
|
|
<div class="step-number">2</div>
|
|
<div class="step-label">Contact Details</div>
|
|
</div>
|
|
<div class="step-indicator" data-step="3">
|
|
<div class="step-number">3</div>
|
|
<div class="step-label">Preferences</div>
|
|
</div>
|
|
<div class="step-indicator" data-step="4">
|
|
<div class="step-number">4</div>
|
|
<div class="step-label">Review</div>
|
|
</div>
|
|
<div class="progress-line">
|
|
<div class="progress-line-fill"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form Content -->
|
|
<div class="form-content">
|
|
<!-- Step 1: Personal Information -->
|
|
<div class="form-step active" data-step="1">
|
|
<h2 style="color: white; margin-bottom: 30px;">Personal Information</h2>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Full Name</label>
|
|
<input type="text" class="form-input" name="fullName" placeholder="Enter your full name" required>
|
|
<span class="error-message">Please enter your full name</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Date of Birth</label>
|
|
<input type="date" class="form-input" name="dateOfBirth" required>
|
|
<span class="error-message">Please select your date of birth</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Gender</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" class="radio-input" name="gender" value="male">
|
|
Male
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" class="radio-input" name="gender" value="female">
|
|
Female
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" class="radio-input" name="gender" value="other">
|
|
Other
|
|
</label>
|
|
</div>
|
|
<span class="error-message">Please select your gender</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Occupation</label>
|
|
<select class="form-select" name="occupation" required>
|
|
<option value="">Select your occupation</option>
|
|
<option value="student">Student</option>
|
|
<option value="employed">Employed</option>
|
|
<option value="self-employed">Self Employed</option>
|
|
<option value="retired">Retired</option>
|
|
<option value="other">Other</option>
|
|
</select>
|
|
<span class="error-message">Please select your occupation</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 2: Contact Details -->
|
|
<div class="form-step" data-step="2">
|
|
<h2 style="color: white; margin-bottom: 30px;">Contact Details</h2>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Email Address</label>
|
|
<input type="email" class="form-input" name="email" placeholder="your@email.com" required>
|
|
<span class="error-message">Please enter a valid email address</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Phone Number</label>
|
|
<input type="tel" class="form-input" name="phone" placeholder="+1 (555) 123-4567" required>
|
|
<span class="error-message">Please enter a valid phone number</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Address</label>
|
|
<textarea class="form-textarea" name="address" rows="3" placeholder="Enter your full address" required></textarea>
|
|
<span class="error-message">Please enter your address</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Preferred Contact Method</label>
|
|
<div class="checkbox-group">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="contactMethod" value="email">
|
|
Email
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="contactMethod" value="phone">
|
|
Phone
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="contactMethod" value="sms">
|
|
SMS
|
|
</label>
|
|
</div>
|
|
<span class="error-message">Please select at least one contact method</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 3: Preferences -->
|
|
<div class="form-step" data-step="3">
|
|
<h2 style="color: white; margin-bottom: 30px;">Preferences</h2>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Newsletter Subscription</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" class="radio-input" name="newsletter" value="yes">
|
|
Yes, subscribe me
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" class="radio-input" name="newsletter" value="no">
|
|
No, thanks
|
|
</label>
|
|
</div>
|
|
<span class="error-message">Please select an option</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Interests</label>
|
|
<div class="checkbox-group">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="interests" value="technology">
|
|
Technology
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="interests" value="design">
|
|
Design
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="interests" value="business">
|
|
Business
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" class="checkbox-input" name="interests" value="health">
|
|
Health
|
|
</label>
|
|
</div>
|
|
<span class="error-message">Please select at least one interest</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Additional Comments</label>
|
|
<textarea class="form-textarea" name="comments" rows="4" placeholder="Any additional information you'd like to share..."></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 4: Review -->
|
|
<div class="form-step" data-step="4">
|
|
<h2 style="color: white; margin-bottom: 30px;">Review Your Information</h2>
|
|
|
|
<div class="summary-content">
|
|
<div class="summary-item">
|
|
<span class="summary-label">Full Name:</span>
|
|
<span class="summary-value" id="summary-name">-</span>
|
|
</div>
|
|
<div class="summary-item">
|
|
<span class="summary-label">Date of Birth:</span>
|
|
<span class="summary-value" id="summary-dob">-</span>
|
|
</div>
|
|
<div class="summary-item">
|
|
<span class="summary-label">Email:</span>
|
|
<span class="summary-value" id="summary-email">-</span>
|
|
</div>
|
|
<div class="summary-item">
|
|
<span class="summary-label">Phone:</span>
|
|
<span class="summary-value" id="summary-phone">-</span>
|
|
</div>
|
|
<div class="summary-item">
|
|
<span class="summary-label">Newsletter:</span>
|
|
<span class="summary-value" id="summary-newsletter">-</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Success Animation -->
|
|
<div class="success-animation">
|
|
<div class="success-icon">✓</div>
|
|
<h2 style="color: white; margin-bottom: 10px;">Submission Successful!</h2>
|
|
<p style="color: rgba(255, 255, 255, 0.7);">Your information has been saved successfully.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Navigation -->
|
|
<div class="form-navigation">
|
|
<div class="save-indicator" id="saveIndicator">
|
|
<div class="save-icon"></div>
|
|
<span id="saveText">All changes saved</span>
|
|
</div>
|
|
|
|
<div style="display: flex; gap: 15px;">
|
|
<button class="btn" id="prevBtn" onclick="changeStep(-1)" disabled>Previous</button>
|
|
<button class="btn btn-primary" id="nextBtn" onclick="changeStep(1)">Next</button>
|
|
<button class="btn btn-primary" id="submitBtn" onclick="submitForm()" style="display: none;">Submit</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let currentStep = 1;
|
|
const totalSteps = 4;
|
|
const formData = {};
|
|
|
|
// Auto-save functionality
|
|
let saveTimeout;
|
|
function autoSave() {
|
|
clearTimeout(saveTimeout);
|
|
const saveIndicator = document.getElementById('saveIndicator');
|
|
const saveText = document.getElementById('saveText');
|
|
|
|
saveIndicator.classList.add('saving');
|
|
saveText.textContent = 'Saving...';
|
|
|
|
saveTimeout = setTimeout(() => {
|
|
// Save to localStorage
|
|
localStorage.setItem('wizardFormData', JSON.stringify(formData));
|
|
localStorage.setItem('wizardCurrentStep', currentStep);
|
|
|
|
saveIndicator.classList.remove('saving');
|
|
saveText.textContent = 'All changes saved';
|
|
}, 1000);
|
|
}
|
|
|
|
// Load saved data on page load
|
|
window.addEventListener('load', () => {
|
|
const savedData = localStorage.getItem('wizardFormData');
|
|
const savedStep = localStorage.getItem('wizardCurrentStep');
|
|
|
|
if (savedData) {
|
|
Object.assign(formData, JSON.parse(savedData));
|
|
// Restore form values
|
|
Object.keys(formData).forEach(key => {
|
|
const elements = document.querySelectorAll(`[name="${key}"]`);
|
|
elements.forEach(element => {
|
|
if (element.type === 'radio' || element.type === 'checkbox') {
|
|
element.checked = element.value === formData[key] ||
|
|
(Array.isArray(formData[key]) && formData[key].includes(element.value));
|
|
} else {
|
|
element.value = formData[key];
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
if (savedStep && savedStep !== '1') {
|
|
currentStep = 1;
|
|
changeStep(parseInt(savedStep) - 1);
|
|
}
|
|
});
|
|
|
|
// Add input listeners for auto-save
|
|
document.querySelectorAll('input, select, textarea').forEach(element => {
|
|
element.addEventListener('input', () => {
|
|
saveFormData();
|
|
autoSave();
|
|
});
|
|
element.addEventListener('change', () => {
|
|
saveFormData();
|
|
autoSave();
|
|
});
|
|
});
|
|
|
|
function saveFormData() {
|
|
const currentStepElement = document.querySelector(`.form-step[data-step="${currentStep}"]`);
|
|
const inputs = currentStepElement.querySelectorAll('input, select, textarea');
|
|
|
|
inputs.forEach(input => {
|
|
if (input.type === 'radio') {
|
|
if (input.checked) {
|
|
formData[input.name] = input.value;
|
|
}
|
|
} else if (input.type === 'checkbox') {
|
|
if (!formData[input.name]) formData[input.name] = [];
|
|
if (input.checked && !formData[input.name].includes(input.value)) {
|
|
formData[input.name].push(input.value);
|
|
} else if (!input.checked && formData[input.name].includes(input.value)) {
|
|
formData[input.name] = formData[input.name].filter(v => v !== input.value);
|
|
}
|
|
} else {
|
|
formData[input.name] = input.value;
|
|
}
|
|
});
|
|
}
|
|
|
|
function validateStep(step) {
|
|
const stepElement = document.querySelector(`.form-step[data-step="${step}"]`);
|
|
const requiredInputs = stepElement.querySelectorAll('[required]');
|
|
let isValid = true;
|
|
|
|
requiredInputs.forEach(input => {
|
|
const formGroup = input.closest('.form-group');
|
|
|
|
if (input.type === 'radio') {
|
|
const radioGroup = stepElement.querySelectorAll(`input[name="${input.name}"]`);
|
|
const isChecked = Array.from(radioGroup).some(radio => radio.checked);
|
|
|
|
if (!isChecked) {
|
|
formGroup.classList.add('error');
|
|
isValid = false;
|
|
} else {
|
|
formGroup.classList.remove('error');
|
|
}
|
|
} else if (input.name === 'contactMethod') {
|
|
const checkboxes = stepElement.querySelectorAll(`input[name="${input.name}"]`);
|
|
const isChecked = Array.from(checkboxes).some(checkbox => checkbox.checked);
|
|
|
|
if (!isChecked) {
|
|
formGroup.classList.add('error');
|
|
isValid = false;
|
|
} else {
|
|
formGroup.classList.remove('error');
|
|
}
|
|
} else if (input.type === 'email') {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!emailRegex.test(input.value)) {
|
|
formGroup.classList.add('error');
|
|
isValid = false;
|
|
} else {
|
|
formGroup.classList.remove('error');
|
|
formGroup.classList.add('success');
|
|
}
|
|
} else if (!input.value.trim()) {
|
|
formGroup.classList.add('error');
|
|
isValid = false;
|
|
} else {
|
|
formGroup.classList.remove('error');
|
|
formGroup.classList.add('success');
|
|
}
|
|
});
|
|
|
|
return isValid;
|
|
}
|
|
|
|
function changeStep(direction) {
|
|
// Validate current step before moving forward
|
|
if (direction > 0 && !validateStep(currentStep)) {
|
|
return;
|
|
}
|
|
|
|
saveFormData();
|
|
|
|
const newStep = currentStep + direction;
|
|
if (newStep < 1 || newStep > totalSteps) return;
|
|
|
|
// Hide current step
|
|
document.querySelector(`.form-step[data-step="${currentStep}"]`).classList.remove('active');
|
|
document.querySelector(`.step-indicator[data-step="${currentStep}"]`).classList.remove('active');
|
|
|
|
if (direction > 0) {
|
|
document.querySelector(`.step-indicator[data-step="${currentStep}"]`).classList.add('completed');
|
|
}
|
|
|
|
// Show new step
|
|
currentStep = newStep;
|
|
document.querySelector(`.form-step[data-step="${currentStep}"]`).classList.add('active');
|
|
document.querySelector(`.step-indicator[data-step="${currentStep}"]`).classList.add('active');
|
|
|
|
// Update progress bar
|
|
const progressPercentage = ((currentStep - 1) / (totalSteps - 1)) * 100;
|
|
document.querySelector('.progress-line-fill').style.width = progressPercentage + '%';
|
|
|
|
// Update navigation buttons
|
|
document.getElementById('prevBtn').disabled = currentStep === 1;
|
|
|
|
if (currentStep === totalSteps) {
|
|
document.getElementById('nextBtn').style.display = 'none';
|
|
document.getElementById('submitBtn').style.display = 'block';
|
|
updateSummary();
|
|
} else {
|
|
document.getElementById('nextBtn').style.display = 'block';
|
|
document.getElementById('submitBtn').style.display = 'none';
|
|
}
|
|
|
|
// Remove completed class from future steps
|
|
for (let i = currentStep + 1; i <= totalSteps; i++) {
|
|
document.querySelector(`.step-indicator[data-step="${i}"]`).classList.remove('completed');
|
|
}
|
|
}
|
|
|
|
function updateSummary() {
|
|
document.getElementById('summary-name').textContent = formData.fullName || '-';
|
|
document.getElementById('summary-dob').textContent = formData.dateOfBirth || '-';
|
|
document.getElementById('summary-email').textContent = formData.email || '-';
|
|
document.getElementById('summary-phone').textContent = formData.phone || '-';
|
|
document.getElementById('summary-newsletter').textContent =
|
|
formData.newsletter === 'yes' ? 'Subscribed' : 'Not Subscribed';
|
|
}
|
|
|
|
function submitForm() {
|
|
// Show success animation
|
|
document.querySelector(`.form-step[data-step="${currentStep}"]`).style.display = 'none';
|
|
document.querySelector('.success-animation').style.display = 'block';
|
|
|
|
// Clear saved data
|
|
localStorage.removeItem('wizardFormData');
|
|
localStorage.removeItem('wizardCurrentStep');
|
|
|
|
// Log form data (in real app, would send to server)
|
|
console.log('Form submitted:', formData);
|
|
|
|
// Reset after delay
|
|
setTimeout(() => {
|
|
if (confirm('Would you like to fill out another form?')) {
|
|
location.reload();
|
|
}
|
|
}, 3000);
|
|
}
|
|
|
|
// Add real-time validation
|
|
document.querySelectorAll('.form-input, .form-select, .form-textarea').forEach(input => {
|
|
input.addEventListener('blur', () => {
|
|
const formGroup = input.closest('.form-group');
|
|
|
|
if (input.hasAttribute('required')) {
|
|
if (input.type === 'email') {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (emailRegex.test(input.value)) {
|
|
formGroup.classList.remove('error');
|
|
formGroup.classList.add('success');
|
|
} else if (input.value) {
|
|
formGroup.classList.add('error');
|
|
}
|
|
} else if (input.value.trim()) {
|
|
formGroup.classList.remove('error');
|
|
formGroup.classList.add('success');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |