2026-04-13 19:04:12 +05:30

182 lines
5.6 KiB
PHP

<?php
$fieldName = $fieldName ?? '';
$fieldLabel = $fieldLabel ?? '';
$fieldId = $fieldId ?? $fieldName;
$fieldValue = $fieldValue ?? '';
$required = $required ?? true;
$validationErrors = $validationErrors ?? [];
$placeholder = $placeholder ?? "Enter " . strtolower($fieldLabel);
$hasError = isset($validationErrors[$fieldName]);
?>
<div class="name-field-component">
<label class="form-label" for="<?= esc($fieldId) ?>">
<?= esc($fieldLabel) ?>
<?php if ($required): ?><span class="text-danger">*</span><?php endif; ?>
</label>
<input
type="text"
name="<?= esc($fieldName) ?>"
id="<?= esc($fieldId) ?>"
value="<?= esc($fieldValue) ?>"
class="form-control name-input <?= $hasError ? 'is-invalid' : '' ?>"
placeholder="<?= esc($placeholder) ?>"
data-field-name="<?= esc($fieldName) ?>"
data-label="<?= esc($fieldLabel) ?>"
<?php if ($required): ?>required<?php endif; ?>
oninput="validateNameField(this)"
onblur="validateNameField(this)"
>
<div class="invalid-feedback" id="<?= esc($fieldId) ?>_error">
<?= $hasError ? esc($validationErrors[$fieldName]) : '' ?>
</div>
</div>
<style>
.name-field-component {
position: relative;
}
.name-input.is-invalid {
border-color: #dc3545;
}
.invalid-feedback {
display: none;
font-size: 0.875em;
color: #dc3545;
margin-top: 0.25rem;
}
.invalid-feedback.show {
display: block;
}
.name-field-component .text-muted {
font-size: 0.75rem;
margin-top: 0.25rem;
display: block;
}
.name-input.is-invalid ~ .text-muted {
display: none;
}
</style>
<script>
function validateNameField(input) {
const fieldName = input.dataset.fieldName;
const fieldLabel = input.dataset.label;
let value = input.value.trim();
const errorElement = document.getElementById(input.id + '_error');
const hintElement = document.getElementById(input.id + '_hint');
// Clear previous validation state
input.classList.remove('is-invalid');
errorElement.classList.remove('show');
errorElement.textContent = '';
if (value === '') {
// Field is empty, check if required
if (input.hasAttribute('required')) {
input.classList.add('is-invalid');
errorElement.textContent = fieldLabel + ' is required';
errorElement.classList.add('show');
hintElement.style.display = 'none';
} else {
hintElement.style.display = 'block';
}
return false;
}
// Check for valid characters (letters only, including spaces for names)
const nameRegex = /^[a-zA-Z\s'-]+$/;
if (!nameRegex.test(value)) {
input.classList.add('is-invalid');
errorElement.textContent = fieldLabel + ' can only contain letters, spaces, hyphens, and apostrophes';
errorElement.classList.add('show');
hintElement.style.display = 'none';
return false;
}
// Check minimum length
if (value.length < 2) {
input.classList.add('is-invalid');
errorElement.textContent = fieldLabel + ' must be at least 2 characters long';
errorElement.classList.add('show');
hintElement.style.display = 'none';
return false;
}
// Check maximum length
if (value.length > 50) {
input.classList.add('is-invalid');
errorElement.textContent = fieldLabel + ' cannot exceed 50 characters';
errorElement.classList.add('show');
hintElement.style.display = 'none';
return false;
}
// Auto-capitalize first letter of each word
const words = value.toLowerCase().split(/\s+/);
const capitalizedWords = words.map(word => {
if (word.length === 0) return '';
return word.charAt(0).toUpperCase() + word.slice(1);
});
const capitalizedValue = capitalizedWords.join(' ');
// Update input value if different
if (input.value !== capitalizedValue) {
input.value = capitalizedValue;
}
// Hide hint and show success
hintElement.style.display = 'none';
input.classList.remove('is-invalid');
input.classList.add('is-valid');
// Remove is-valid class after a short delay
setTimeout(() => {
input.classList.remove('is-valid');
}, 2000);
return true;
}
// Prevent non-letter characters on keypress
document.addEventListener('DOMContentLoaded', function() {
const nameInputs = document.querySelectorAll('.name-input');
nameInputs.forEach(input => {
input.addEventListener('keypress', function(e) {
const char = String.fromCharCode(e.which || e.keyCode);
const isAllowed = /^[a-zA-Z\s'-]$/.test(char);
if (!isAllowed) {
e.preventDefault();
return false;
}
});
// Prevent paste of invalid characters
input.addEventListener('paste', function(e) {
e.preventDefault();
const pastedData = (e.clipboardData || window.clipboardData).getData('text');
const cleanedData = pastedData.replace(/[^a-zA-Z\s'-]/g, '');
// Insert cleaned data at cursor position
const start = this.selectionStart;
const end = this.selectionEnd;
const currentValue = this.value;
const newValue = currentValue.substring(0, start) + cleanedData + currentValue.substring(end);
this.value = newValue;
this.selectionStart = this.selectionEnd = start + cleanedData.length;
validateNameField(this);
});
});
});
</script>