This commit is contained in:
KANE LAZENI 2026-02-14 15:06:53 +00:00
parent 71b7c83738
commit c7a72b5d4f

View File

@ -3,307 +3,95 @@
?> ?>
<style> <style>
/* Champ NFC complètement caché et sécurisé */ /* Masquage du texte */
#donneesCarte { #donneesCarte {
position: absolute !important; color: transparent !important;
left: -9999px !important; text-shadow: 0 0 8px rgba(0,0,0,0.5) !important;
top: -9999px !important; user-select: none !important;
opacity: 0 !important; }
pointer-events: none !important;
width: 1px !important;
height: 1px !important;
z-index: -1 !important;
}
/* Zone d'affichage visuel principale */ #donneesCarte::placeholder {
.nfc-status-display { color: #6c757d !important;
font-size: 24pt; text-shadow: none !important;
min-height: 200px; }
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 3px dashed #ccc;
border-radius: 15px;
background: #f8f9fa;
margin: 30px auto;
max-width: 600px;
transition: all 0.3s ease;
padding: 30px;
}
.nfc-status-display.reading { /* Animation lors de la saisie */
border-color: #4caf50; #donneesCarte.reading {
background: #e8f5e9; border-color: #4caf50 !important;
animation: glow 1.5s infinite; box-shadow: 0 0 0 0.2rem rgba(76, 175, 80, 0.25) !important;
} animation: pulse-border 1s infinite;
}
.nfc-status-display.error { @keyframes pulse-border {
border-color: #dc3545; 0%, 100% { border-color: #4caf50; }
background: #f8d7da; 50% { border-color: #66bb6a; }
} }
@keyframes glow { /* Indicateur visuel simple */
0%, 100% { box-shadow: 0 0 10px rgba(76, 175, 80, 0.3); } .reading-indicator {
50% { box-shadow: 0 0 25px rgba(76, 175, 80, 0.6); } display: none;
}
/* Icône NFC animée */
.nfc-icon {
font-size: 100px;
margin-bottom: 20px;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.08); opacity: 0.85; }
}
.nfc-status-display.reading .nfc-icon {
animation: rotate-pulse 1.2s linear infinite;
}
@keyframes rotate-pulse {
0% { transform: rotate(0deg) scale(1); }
50% { transform: rotate(180deg) scale(1.1); }
100% { transform: rotate(360deg) scale(1); }
}
/* Texte du statut */
#nfc-placeholder {
font-size: 20px;
color: #666;
font-weight: 500;
text-align: center; text-align: center;
}
/* Points de feedback visuel */
#nfc-dots {
letter-spacing: 15px;
color: #4caf50; color: #4caf50;
font-size: 40px; font-size: 18px;
margin-top: 15px; margin-top: 10px;
font-weight: bold; }
}
/* Spinner de validation - utilise votre spinner existant */ .reading-indicator.active {
#div_wait_nfc { display: block;
text-align: center; }
min-height: 50px; </style>
}
/* Adaptation de votre alerte existante */ <form id="frmrechercheparcarte" name="frmrechercheparcarte" method="post" action="Rechercheparcarte/index/">
.alert { <INPUT style='font-size:40pt; height: 50px; text-align: center;'
margin-top: 20px; class="form-control"
border-radius: 10px; TYPE="text"
animation: slideIn 0.3s ease; id="donneesCarte"
} name="donneesCarte"
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Container responsive */
.nfc-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
/* Info section */
.info-helper {
background: #e9ecef;
border-radius: 10px;
padding: 15px;
margin-top: 20px;
font-size: 14px;
color: #495057;
text-align: center;
}
.info-helper i {
color: #4caf50;
margin-right: 8px;
}
</style>
<div class="nfc-container">
<form id="frmrechercheparcarte" name="frmrechercheparcarte" method="post" action="Rechercheparcarte/index/">
<!-- Champ invisible mais fonctionnel (conserve votre logique) -->
<input type="text"
id="donneesCarte_1"
name="donneesCarte_1"
autofocus autofocus
autocomplete="off" AUTOCOMPLETE="OFF"
tabindex="-1"> placeholder="<?= _("Veuillez scanner la carte NFC!")?>">
<!-- Bouton submit caché (conservé pour compatibilité) --> <div class="reading-indicator" id="reading-indicator">
<input id="lancerrechercheparcarte" <i class="fa fa-check-circle"></i> <?= _("Carte détectée") ?>
name="lancerrechercheparcarte"
class="sr-only"
type="submit"
value="<?= _("Rechercher") ?>">
<!-- Zone d'affichage visuel -->
<div id="nfc-display" class="nfc-status-display">
<div class="nfc-icon">📱</div>
<span id="nfc-placeholder"><?= _("Veuillez scanner la carte NFC!") ?></span>
<span id="nfc-dots" style="display:none;"></span>
</div> </div>
</form> <input id="lancerrechercheparcarte" name="lancerrechercheparcarte" class="sr-only" type="submit" value="<?= _("Rechercher") ?>" >
</form>
<!-- Votre spinner existant --> <div id ="div_wait_nfc"> </div>
<div id="div_wait_nfc"></div>
<!-- Votre message d'erreur existant --> <?php if (isset($msgErreur) && $msgErreur>" "): ?>
<?php if (isset($msgErreur) && $msgErreur > " "): ?>
<div class="alert alert-danger" style="height:38px; padding:5px; text-align: center;"> <div class="alert alert-danger" style="height:38px; padding:5px; text-align: center;">
<H4><?= $msgErreur ?></H4> <H4><?= $msgErreur ?></H4>
</div> </div>
<?php endif; ?> <?php endif; ?>
<!-- Section d'aide -->
<div class="info-helper">
<i class="fa fa-info-circle"></i>
<?= _("Positionnez la carte NFC sur le lecteur pour démarrer la recherche automatique") ?>
</div>
</div>
<script> <script>
// Configuration const inputField = document.getElementById('donneesCarte');
const NFC_CONFIG = { const indicator = document.getElementById('reading-indicator');
minLength: 3, // Longueur minimale (votre logique actuelle)
autoSubmitDelay: 200, // Délai avant soumission (ms)
refocusDelay: 10 // Délai avant re-focus (ms)
};
// Éléments DOM // Protection
const nfcElements = { inputField.addEventListener('contextmenu', e => e.preventDefault());
input: document.getElementById('donneesCarte'), inputField.addEventListener('copy', e => e.preventDefault());
display: document.getElementById('nfc-display'), inputField.addEventListener('cut', e => e.preventDefault());
placeholder: document.getElementById('nfc-placeholder'),
dots: document.getElementById('nfc-dots'),
form: document.getElementById('frmrechercheparcarte'),
waitDiv: document.getElementById('div_wait_nfc')
};
// Réinitialiser l'affichage // Feedback visuel pendant la saisie
function resetNFCDisplay() { inputField.addEventListener('input', function() {
nfcElements.display.className = 'nfc-status-display'; if (this.value.length > 0) {
nfcElements.placeholder.style.display = 'block'; this.classList.add('reading');
nfcElements.placeholder.textContent = '<?= _("Veuillez scanner la carte NFC!") ?>'; indicator.classList.add('active');
nfcElements.placeholder.style.color = '';
nfcElements.dots.style.display = 'none';
nfcElements.waitDiv.innerHTML = '';
}
// Afficher le spinner de chargement (votre logique existante)
function showLoadingSpinner() {
nfcElements.waitDiv.innerHTML = '<div style="padding-top:80px; text-align:center; font-size:14px; color: #4caf50;"><span><i class="fa fa-spinner fa-spin fa-5x"></i></span></div>';
}
// Gestion de la saisie avec événement 'change' (conserve votre logique)
nfcElements.input.addEventListener('change', function() {
if (this.value.length > NFC_CONFIG.minLength) {
showLoadingSpinner();
this.form.submit();
}
});
// Gestion de la saisie en temps réel pour le feedback visuel
nfcElements.input.addEventListener('input', function() {
const length = this.value.length;
if (length > 0) {
// Activer le mode "lecture"
nfcElements.display.classList.add('reading');
nfcElements.placeholder.style.display = 'none';
nfcElements.dots.style.display = 'block';
// Afficher des points (maximum 10 pour ne pas surcharger)
nfcElements.dots.textContent = '•'.repeat(Math.min(length, 10));
// Si longueur suffisante, préparer la soumission
if (length > NFC_CONFIG.minLength) {
nfcElements.placeholder.textContent = '<?= _("Validation en cours...") ?>';
nfcElements.placeholder.style.display = 'block';
nfcElements.placeholder.style.color = '#4caf50';
nfcElements.dots.style.display = 'none';
}
} else { } else {
resetNFCDisplay(); this.classList.remove('reading');
indicator.classList.remove('active');
} }
}); });
// Maintenir le focus sur le champ caché // Votre logique existante
nfcElements.input.addEventListener('blur', function() { inputField.addEventListener('change', function () {
setTimeout(() => { if (this.value.length > 3) {
this.focus(); var div_wait_nfc = $('#div_wait_nfc');
}, NFC_CONFIG.refocusDelay); div_wait_nfc.html('<div style="padding-top:80px; text-align:center; font-size:14px; color: #4caf50;"><span><i class="fa fa-spinner fa-spin fa-5x" >' + '</span></div>');
});
// Empêcher les actions de copier/coller/menu contextuel
nfcElements.input.addEventListener('contextmenu', e => e.preventDefault());
nfcElements.input.addEventListener('copy', e => e.preventDefault());
nfcElements.input.addEventListener('cut', e => e.preventDefault());
nfcElements.input.addEventListener('paste', e => e.preventDefault());
// Gestion des touches clavier
nfcElements.input.addEventListener('keydown', function(e) {
// Échap pour réinitialiser
if (e.key === 'Escape') {
e.preventDefault();
this.value = '';
resetNFCDisplay();
}
// Empêcher Tab
if (e.key === 'Tab') {
e.preventDefault();
}
// Enter force la soumission si assez de caractères
if (e.key === 'Enter' && this.value.length > NFC_CONFIG.minLength) {
e.preventDefault();
showLoadingSpinner();
this.form.submit(); this.form.submit();
} }
}); });
// Focus initial
window.addEventListener('load', function() {
nfcElements.input.focus();
});
// Re-focus au clic sur la page
document.addEventListener('click', function(e) {
// Ne pas refocus si on clique sur un élément interactif
if (e.target.tagName !== 'A' &&
e.target.tagName !== 'BUTTON' &&
e.target.tagName !== 'INPUT' &&
e.target.type !== 'submit') {
nfcElements.input.focus();
}
});
// Gestion de la visibilité de la page
document.addEventListener('visibilitychange', function() {
if (!document.hidden) {
resetNFCDisplay();
nfcElements.input.focus();
}
});
// Log de démarrage (retirer en production)
console.log('NFC Reader initialisé - Mode sécurisé');
</script> </script>