Gestion avancée des événements de focus et des temporisateurs en JavaScript

Détection de l'élément ciblé après un événement blur

Dans le développement d'interfaces web, il est courant de valider un champ de saisie dès qu'il perd le focus (événement blur). Cependant, un problème survient si l'utilisateur clique sur un bouton d'action critique (comme "Déconnexion" ou "Annuler") juste après. Déclencher la validation bloquerait l'action souhaitée. L'objectif est donc d'identifier l'élément qui va recevoir le focus suite au blur.

function inspecterElementActif(evt) {
    // Tentative de récupération de l'élément cible selon le navigateur
    const cibleFocus = evt.explicitOriginalTarget || document.activeElement;
    console.log("Élément actif :", cibleFocus.tagName);
}

// Utilisation avec jQuery
$('#monBouton').on('click', function() {
    const idElementActif = $(document.activeElement).attr('id');
    if (idElementActif === 'monBouton') {
        console.log("Le bouton est bien l'élément actif.");
    }
});

Problèmes de compatibilité inter-navigateurs

L'approche utilisant document.activeElement directement dans le gestionnaire blur fonctinone sur d'anciennes versions d'Internet Explorer. Cependant, sur Firefox et Chrome, document.activeElement retourne souvent <body>. Cela s'explique par le cycle des événements : lors du déclenchement de blur, le nouvel élément n'a pas encore reçu le focus. Ce n'est qu'après la fin de l'événement blur que le focus est effectivement transféré.

Solution universelle : Le délai d'exécution avec setTimeout

Puisque le clic sur un bouton spécial se produit toujours après l'événement blur du champ de saisie, il est impossible de connaître l'état futur directement dans le gestionniare blur. La solution consiste à décaler l'exécution de la validation en utilisant setTimeout. Cela laisse le temps au navigateur de transférer le focus avant d'exécuter la logique de validation.

let boutonSpecialClique = false;

function gererClicBoutonSpecial() {
    boutonSpecialClique = true;
    // Logique spécifique au bouton spécial
}

function declencherValidationBlur() {
    // Délai de 50ms pour laisser le temps au focus de se déplacer
    setTimeout(() => {
        executerValidationDifferee();
    }, 50);
}

function executerValidationDifferee() {
    if (!boutonSpecialClique) {
        // Exécuter la validation du formulaire ici
        console.log("Validation en cours...");
    } else {
        console.log("Validation ignorée car bouton spécial cliqué.");
    }
}

Identification de la version de jQuery et du navigateur

Pour vérifier la version de jQuery chargée dans votre environnement :

// Récupération de la chaîne de version
const versionJQuery = $.fn.jquery;
console.log("Version jQuery actuelle :", versionJQuery);

Concernant la détection du navigateur, bien que la propriété $.browser ait été supprimée dans les versions récentes de jQuery (à partir de la 1.9), voici comment elle était structurée historiquement pour identifier les moteurs de rendu :

$(document).ready(function() {
    const navigateur = $.browser;
    let messageResultat = "Navigateur non identifié.";

    if (navigateur.msie) {
        messageResultat = "Internet Explorer version " + navigateur.version;
    } else if (navigateur.mozilla) {
        messageResultat = "Mozilla Firefox";
    } else if (navigateur.webkit) {
        messageResultat = navigateur.safari ? "Safari" : "Chrome (Webkit)";
    } else if (navigateur.opera) {
        messageResultat = "Opera";
    }

    $('#zoneAffichage').text(messageResultat);
});

Temporisateurs : setTimeout vs setInterval

setInterval exécute une fonction de manière répétée à un intervalle fixe (en millisecondes), jusqu'à ce que clearInterval soit appelé. setTimeout, en revanche, n'exécute la fonction qu'une seule fois après un délai spécifié.

// Exécution unique après 3 secondes
setTimeout(maFonction, 3000);

// Exécution répétée toutes les 3 secondes
const idIntervalle = setInterval(maFonction, 3000);

// Pour arrêter l'intervalle
// clearInterval(idIntervalle);

Passage de paramètres à setTimeout. Par défaut, passer des paramètres via une chaîne de caractères est déconseillé. Voici une méthode propre pour encapsuler les arguments en utilisant apply :

const originalSetTimeout = window.setTimeout;

window.setTimeout = function(fn, delai, ...args) {
    const fonctionEncapsulee = function() {
        fn.apply(null, args);
    };
    originalSetTimeout(fonctionEncapsulee, delai);
};

// Exemples d'utilisation
function afficherMessage(msg) {
    console.log(msg);
}

function calculerSomme(x, y, z) {
    console.log(x + y + z);
}

window.setTimeout(afficherMessage, 1000, "Bonjour");
window.setTimeout(calculerSomme, 2000, 10, 20, 30);

Différence fondamentale dans la boucle d'exécution. setInterval tente de maintenir un intervalle strict, ce qui peut entraîner un chevauchement des exécutions si la fonction prend trop de temps. À l'inverse, l'utilisation de setTimeout de manière récursive garentit qu'un nouveau délai est appliqué après la fin de l'exécution de la fonction précédente. Cela évite les conflits pour les tâches lourdes.

function tacheRecurrente() {
    // Traitement long ou complexe ici
    console.log("Traitement terminé");

    // Planification de la prochaine exécution
    setTimeout(tacheRecurrente, 2000);
}

// Démarrage
setTimeout(tacheRecurrente, 2000);

Étiquettes: JavaScript jQuery dom-events setTimeout setInterval

Publié le 14 juillet à 02h55