forked from danielmeppiel/corporate-website
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
342 lines (296 loc) · 9.42 KB
/
main.js
File metadata and controls
342 lines (296 loc) · 9.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
// Corporate Website JavaScript - Demonstrating APM Compliance Standards
/**
* Main application entry point
* Follows compliance guidelines for data handling and accessibility
*/
// Initialize application when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
console.log('🚀 Corporate Website initialized with APM standards');
initializeAccessibility();
initializeGDPRCompliance();
});
/**
* Show welcome message - demonstrates user interaction logging for audit trails
*/
function showMessage() {
// Log user interaction (compliance requirement for audit trails)
logUserInteraction('cta_button_click', {
timestamp: new Date().toISOString(),
action: 'hero_cta_clicked',
user_agent: navigator.userAgent.substring(0, 100) // Truncated for privacy
});
alert('🎉 Welcome! This site is built with APM dependencies for compliance and design standards.');
}
/**
* Handle contact form submission with GDPR compliance
* @param {Event} event - Form submission event
*/
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const data = {
name: formData.get('name'),
email: formData.get('email'),
message: formData.get('message'),
timestamp: new Date().toISOString(),
consent: true // In real app, this would come from explicit consent checkbox
};
// Validate required fields
if (!data.name || !data.email || !data.message) {
showError('All fields are required. Please complete the form.');
return;
}
// Email validation (basic)
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
showError('Please enter a valid email address.');
return;
}
// Log form submission for compliance audit trail
logUserInteraction('form_submission', {
timestamp: data.timestamp,
fields_submitted: ['name', 'email', 'message'],
data_processing_consent: data.consent
});
// Simulate form submission
showSuccess('Thank you for your message! We\'ll get back to you soon.');
event.target.reset();
}
/**
* Initialize accessibility features
* Following design-guidelines package standards
*/
function initializeAccessibility() {
// Add skip link for keyboard navigation
const skipLink = document.createElement('a');
skipLink.href = '#main';
skipLink.textContent = 'Skip to main content';
skipLink.className = 'skip-link';
skipLink.style.cssText = `
position: absolute;
top: -40px;
left: 6px;
background: #2563eb;
color: white;
padding: 8px;
text-decoration: none;
border-radius: 4px;
transition: top 0.3s;
`;
skipLink.addEventListener('focus', () => {
skipLink.style.top = '6px';
});
skipLink.addEventListener('blur', () => {
skipLink.style.top = '-40px';
});
document.body.insertBefore(skipLink, document.body.firstChild);
// Enhance form accessibility
const formInputs = document.querySelectorAll('input, textarea');
formInputs.forEach(input => {
// Add aria-invalid for validation states
input.addEventListener('invalid', () => {
input.setAttribute('aria-invalid', 'true');
});
input.addEventListener('input', () => {
if (input.validity.valid) {
input.removeAttribute('aria-invalid');
}
});
});
console.log('♿ Accessibility features initialized');
}
/**
* Initialize GDPR compliance features
* Following compliance-rules package standards
*/
function initializeGDPRCompliance() {
// Check for existing consent
const consent = localStorage.getItem('gdpr_consent');
if (!consent) {
// In a real application, show consent banner
console.log('🔒 GDPR compliance: No existing consent found');
// showConsentBanner(); // Would implement consent management
}
// Set up data retention policy (7 years for audit logs)
const retentionPolicy = {
audit_logs: 7 * 365 * 24 * 60 * 60 * 1000, // 7 years in milliseconds
user_interactions: 1 * 365 * 24 * 60 * 60 * 1000, // 1 year
performance_logs: 30 * 24 * 60 * 60 * 1000 // 30 days
};
// Clean up old data based on retention policy
cleanupExpiredData(retentionPolicy);
console.log('🔒 GDPR compliance features initialized');
}
/**
* Log user interactions for compliance audit trail
* @param {string} eventType - Type of interaction
* @param {Object} eventData - Event details
*/
function logUserInteraction(eventType, eventData) {
const logEntry = {
id: generateUUID(),
type: eventType,
data: eventData,
ip_hash: 'hashed_ip', // In real app, hash the IP for privacy
session_id: getSessionId(),
timestamp: new Date().toISOString()
};
// Store in localStorage for demo (in production, would send to secure backend)
const logs = JSON.parse(localStorage.getItem('audit_logs') || '[]');
logs.push(logEntry);
// Keep only last 100 entries for demo
if (logs.length > 100) {
logs.shift();
}
localStorage.setItem('audit_logs', JSON.stringify(logs));
console.log('📊 User interaction logged:', eventType);
}
/**
* Clean up expired data based on retention policy
* @param {Object} retentionPolicy - Retention periods for different data types
*/
function cleanupExpiredData(retentionPolicy) {
const now = Date.now();
// Clean up audit logs
const auditLogs = JSON.parse(localStorage.getItem('audit_logs') || '[]');
const validLogs = auditLogs.filter(log => {
const logAge = now - new Date(log.timestamp).getTime();
return logAge < retentionPolicy.audit_logs;
});
if (validLogs.length !== auditLogs.length) {
localStorage.setItem('audit_logs', JSON.stringify(validLogs));
console.log(`🗑️ Cleaned up ${auditLogs.length - validLogs.length} expired audit logs`);
}
}
/**
* Generate UUID for log entries
* @returns {string} UUID string
*/
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* Get or create session ID
* @returns {string} Session ID
*/
function getSessionId() {
let sessionId = sessionStorage.getItem('session_id');
if (!sessionId) {
sessionId = generateUUID();
sessionStorage.setItem('session_id', sessionId);
}
return sessionId;
}
/**
* Show success message with accessibility support
* @param {string} message - Success message
*/
function showSuccess(message) {
const notification = createNotification(message, 'success');
document.body.appendChild(notification);
// Announce to screen readers
announceToScreenReader(message);
// Auto-remove after 5 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
}, 5000);
}
/**
* Show error message with accessibility support
* @param {string} message - Error message
*/
function showError(message) {
const notification = createNotification(message, 'error');
document.body.appendChild(notification);
// Announce to screen readers
announceToScreenReader(message, 'assertive');
// Auto-remove after 7 seconds (longer for errors)
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
}, 7000);
}
/**
* Create notification element
* @param {string} message - Notification message
* @param {string} type - Notification type (success, error)
* @returns {HTMLElement} Notification element
*/
function createNotification(message, type) {
const notification = document.createElement('div');
notification.textContent = message;
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
padding: 16px 24px;
border-radius: 8px;
color: white;
font-weight: 600;
z-index: 1000;
max-width: 400px;
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
background-color: ${type === 'success' ? '#059669' : '#dc2626'};
`;
// Add close button for accessibility
const closeButton = document.createElement('button');
closeButton.textContent = '×';
closeButton.style.cssText = `
background: none;
border: none;
color: white;
font-size: 20px;
float: right;
margin-left: 16px;
cursor: pointer;
line-height: 1;
`;
closeButton.addEventListener('click', () => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
});
notification.appendChild(closeButton);
return notification;
}
/**
* Announce message to screen readers
* @param {string} message - Message to announce
* @param {string} priority - Announcement priority (polite, assertive)
*/
function announceToScreenReader(message, priority = 'polite') {
const announcement = document.createElement('div');
announcement.setAttribute('aria-live', priority);
announcement.setAttribute('aria-atomic', 'true');
announcement.style.cssText = `
position: absolute;
left: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
`;
document.body.appendChild(announcement);
announcement.textContent = message;
// Remove after announcement
setTimeout(() => {
if (announcement.parentNode) {
announcement.parentNode.removeChild(announcement);
}
}, 1000);
}
// Export functions for potential testing or external use
window.corporateWebsite = {
showMessage,
handleSubmit,
logUserInteraction
};
// Make functions globally available (for inline event handlers)
window.showMessage = showMessage;
window.handleSubmit = handleSubmit;