Untitled
2 months ago in HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jonathan Roumie Meet & Greet</title>
<style>
body {
font-family: 'Roboto', sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
background-color: #fafafa;
}
form {
background-color: #fff;
padding: 2rem;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 2rem;
}
h2 {
font-size: 2rem;
color: #333;
margin-bottom: 1rem;
text-align: center;
}
label {
display: block;
font-size: 1.1rem;
margin-bottom: 0.5rem;
color: #555;
}
label.description {
font-size: 0.85rem;
font-style: italic;
margin-top: -0.5rem;
margin-bottom: 1rem;
}
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="datetime-local"],
textarea,
select,
input[type="file"] {
width: 100%;
padding: 0.75rem;
margin-bottom: 1rem;
border-radius: 4px;
border: 1px solid #ddd;
font-size: 1rem;
line-height: 1.5;
color: #333;
}
textarea {
height: 12rem;
resize: vertical;
}
canvas {
border: 1px solid #ddd;
margin-top: 1rem;
}
#canvas-container {
margin-top: 1rem;
}
.checkbox-container {
display: flex;
align-items: center;
margin-top: 1rem;
}
.checkbox-container input[type="checkbox"] {
margin-right: 0.5rem;
}
.checkbox-container label {
margin-left: 0.5rem;
font-size: 0.9rem;
color: #555;
}
button {
margin-top: 1rem;
padding: 0.75rem 1.5rem;
border-radius: 4px;
border: none;
background-color: #007bff;
color: #fff;
font-size: 1rem;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.form-validation.was-validated :invalid,
.form-validation.was-validated :invalid:focus {
border: 1px solid red;
}
.form-validation.was-validated .form-control:valid,
.form-validation.was-validated .form-control:valid:focus,
.form-validation.was-validated .form-control:valid:focus:not(:focus-within) {
border: 1px solid green;
}
.form-validation input[type="submit"]:disabled {
background-color: #c0c0c0;
cursor: not-allowed;
}
#canvas-container canvas {
width: 100%;
height: 100%;
touch-action: none;
}
#canvas-container {
border: 1px solid #ccc;
width: 400px;
height: 100px;
}
#canvas-container {
overflow: hidden;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script>
</head>
<body>
<h2>JONATHAN ROUMIE MEET & GREET APPLICATION</h2>
<!-- User Information Form -->
<form id="user-information-form" class="form-validation needs-validation" novalidate>
<h2>User Information</h2>
<label for="first-name">First Name:</label>
<input type="text" id="first-name" name="first-name" required>
<label class="description">Please enter your first name.</label>
<label for="last-name">Last Name:</label>
<input type="text" id="last-name" name="last-name" required>
<label class="description">Please enter your last name.</label>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label class="description">Please enter a valid email address.</label>
<label for="phone">Phone Number:</label>
<input type="tel" id="phone" name="phone" required pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
<label class="description">Please enter a valid phone number in the format: 123-456-7890.</label>
<label for="street-address">Street Address:</label>
<input type="text" id="street-address" name="street-address" required>
<label class="description">Please enter your street address.</label>
<label for="city">City:</label>
<input type="text" id="city" name="city" required>
<label class="description">Please enter your city.</label>
<label for="state">State:</label>
<input type="text" id="state" name="state" required>
<label class="description">Please enter your state.</label>
<label for="zip">ZIP Code:</label>
<input type="text" id="zip" name="zip" required pattern="[0-9]{5}">
<label class="description">Please enter a valid ZIP code.</label>
<button type="submit">Next</button>
</form>
<!-- Meeting Details Form -->
<form id="meeting-details-form" class="form-validation needs-validation" novalidate>
<h2>Meeting Details</h2>
<label for="meet-time">Preferred Meeting Date and Time:</label>
<input type="datetime-local" id="meet-time" name="meet-time" required>
<label for="meet-type">Type of Meet & Greet:</label>
<select id="meet-type" name="meet-type" required>
<option value="General">General</option>
<option value="Private">Private</option>
</select>
<label for="meet-purpose">Purpose of Meeting:</label>
<textarea id="meet-purpose" name="meet-purpose" required></textarea>
<button type="submit">Next</button>
</form>
<!-- File Uploads Form -->
<form id="file-uploads-form" class="form-validation needs-validation" novalidate>
<h2>File Uploads</h2>
<label for="identification-documents">Upload Identification Documents:</label>
<input type="file" id="identification-documents" name="identification-documents" accept=".pdf,.jpg,.jpeg,.png" required>
<button type="submit">Next</button>
</form>
<!-- Digital Signature Form -->
<form id="digital-signature-form" class="form-validation needs-validation" novalidate>
<h2>Digital Signature</h2>
<div id="canvas-container"></div>
<div class="checkbox-container">
<input type="checkbox" id="terms-conditions" name="terms-conditions" required>
<label for="terms-conditions">I agree to the terms and conditions</label>
</div>
<button type="submit">Finish</button>
</form>
<!-- Scripts -->
<script src="html2pdf.bundle.min.js"></script>
<script src="form_uxui.js"></script>
<script src="form_security.js"></script>
<script src="../form_validation.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Secure file upload by scanning for viruses (This is a placeholder implementation)
const fileInput = document.querySelector('input[type="file"]');
if (fileInput) {
fileInput.addEventListener('change', () => {
const file = fileInput.files[0];
if (file) {
setTimeout(() => {
const isClean = Math.random() > 0.005;
if (isClean) {
console.log('File is clean.');
} else {
console.log('File contains a virus! Please upload a different file.');
alert('File contains a virus! Please upload a different file.');
fileInput.value = '';
}
}, 2000);
}
});
}
});
document.addEventListener('DOMContentLoaded', () => {
// Add custom validation for forms
const forms = document.querySelectorAll('.form-validation');
forms.forEach((form) => {
form.addEventListener('submit', (event) => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
// Capture digital signature
const canvasContainer = document.getElementById('canvas-container');
if (canvasContainer) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const signatureColor = 'black';
const signatureWidth = 2;
let isDrawing = false;
let latestPosition = { x: 0, y: 0 };
canvas.width = 400;
canvas.height = 100;
canvasContainer.appendChild(canvas);
const getTouchPosition = (touchEvent) => {
const rect = canvas.getBoundingClientRect();
return {
x: touchEvent.touches[0].clientX - rect.left,
y: touchEvent.touches[0].clientY - rect.top
};
};
const getMousePosition = (mouseEvent) => {
const rect = canvas.getBoundingClientRect();
return {
x: mouseEvent.clientX - rect.left,
y: mouseEvent.clientY - rect.top
};
};
const draw = (x1, y1, x2, y2) => {
ctx.lineWidth = signatureWidth;
ctx.strokeStyle = signatureColor;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
};
const startDrawing = (position) => {
isDrawing = true;
latestPosition = position;
};
const stopDrawing = () => {
isDrawing = false;
};
const moveDrawing = (position) => {
if (isDrawing) {
draw(latestPosition.x, latestPosition.y, position.x, position.y);
latestPosition = position;
}
};
// Mouse events
canvas.addEventListener('mousedown', (e) => startDrawing(getMousePosition(e)));
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mousemove', (e) => moveDrawing(getMousePosition(e)));
// Touch events
canvas.addEventListener('touchstart', (e) => {
e.preventDefault(); // Prevent scrolling when touching the canvas
startDrawing(getTouchPosition(e));
});
canvas.addEventListener('touchend', stopDrawing);
canvas.addEventListener('touchmove', (e) => {
e.preventDefault(); // Prevent scrolling when touching the canvas
moveDrawing(getTouchPosition(e));
});
}
// Reset forms when they are navigated to
forms.forEach((form) => {
form.addEventListener('reset', () => {
form.classList.remove('was-validated');
});
});
});
const userForm = document.getElementById('user-information-form');
const meetingForm = document.getElementById('meeting-details-form');
const fileForm = document.getElementById('file-uploads-form');
const signatureForm = document.getElementById('digital-signature-form');
const formValidation = (form) => {
const formElements = [...form.elements];
return formElements.every((element) => {
if (element.type === 'submit') {
return true;
}
if (element.checkValidity) {
return element.checkValidity();
}
return true;
});
};
const resetForm = (form) => {
form.reset();
form.classList.remove('was-validated');
};
const addEventListeners = (form) => {
form.addEventListener('submit', (event) => {
event.preventDefault();
if (formValidation(form)) {
// Form is valid, generate PDF and perform necessary actions
const element = form;
html2pdf().from(element).save();
} else {
form.classList.add('was-validated');
}
});
};
addEventListeners(userForm);
addEventListeners(meetingForm);
addEventListeners(fileForm);
addEventListeners(signatureForm);
(function() {
'use strict';
window.addEventListener('load', function() {
var forms = document.getElementsByClassName('needs-validation');
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
// Initialize Google Places Autocomplete
function initializeAutocomplete() {
const addressInput = document.getElementById('street-address');
const autocomplete = new google.maps.places.Autocomplete(addressInput, { types: ['address'] });
autocomplete.addListener('place_changed', () => {
const place = autocomplete.getPlace();
const addressComponents = place.address_components;
if (addressComponents) {
addressComponents.forEach(component => {
const componentType = component.types[0];
const value = component.long_name;
switch (componentType) {
case 'street_number':
document.getElementById('street-address').value = value;
break;
case 'route':
document.getElementById('street-address').value += ' ' + value;
break;
case 'locality':
document.getElementById('city').value = value;
break;
case 'administrative_area_level_1':
document.getElementById('state').value = value;
break;
case 'postal_code':
document.getElementById('zip').value = value;
break;
}
});
}
});
}
google.maps.event.addDomListener(window, 'load', initializeAutocomplete);
</script>
</body>
</html>