Contexte
Je suis tombé sur cette question en essayant d'écrire des tests automatisés, pour vérifier qu'un certain ensemble d'éléments sur une page donnée reçoivent tous les propriétés css définies par le css pour les événements de survol.
Bien que la réponse ci-dessus explique parfaitement pourquoi il n'est pas possible de déclencher simplement l'événement de survol par JS et de sonder ensuite une valeur CSS intéressante, elle ne répond que partiellement à la question initiale "Comment puis-je simuler un survol de souris en JavaScript pur qui active le CSS ":hover" ?
Avis de non-responsabilité
Ce n'est pas une solution performante. Nous l'utilisons uniquement pour les tests automatisés, où les performances ne sont pas un problème.
Solution
simulateCssEvent = function(type){
var id = 'simulatedStyle';
var generateEvent = function(selector){
var style = "";
for (var i in document.styleSheets) {
var rules = document.styleSheets[i].cssRules;
for (var r in rules) {
if(rules[r].cssText && rules[r].selectorText){
if(rules[r].selectorText.indexOf(selector) > -1){
var regex = new RegExp(selector,"g")
var text = rules[r].cssText.replace(regex,"");
style += text+"\n";
}
}
}
}
$("head").append("<style id="+id+">"+style+"</style>");
};
var stopEvent = function(){
$("#"+id).remove();
};
switch(type) {
case "hover":
return generateEvent(":hover");
case "stop":
return stopEvent();
}
}
Explication
generateEvent lit tous les fichiers css, remplace :hover par une chaîne vide et l'applique. Cela a pour effet d'appliquer tous les styles :hover. On peut maintenant rechercher un style de survol et revenir à l'état initial en arrêtant la simulation.
Pourquoi appliquer l'effet de survol à l'ensemble du document et pas seulement à l'élément concerné en le récupérant dans les feuilles et en effectuant ensuite un element.css(...) ?
Ainsi, le style serait appliqué en ligne, ce qui remplacerait d'autres styles, qui pourraient ne pas être remplacés par le style de survol css original.
Comment puis-je maintenant simuler le survol d'un seul élément ?
Ce n'est pas performant, donc mieux vaut ne pas le faire. Si vous devez le faire, vous pouvez vérifier avec element.is(selectorOfInterest) si le style s'applique à votre élément et n'utiliser que ces styles.
Ejemplo
Dans Jasmine, vous pouvez par exemple maintenant exécuter :
describe("Simulate CSS Event", function() {
it("Simulate Link Hover", function () {
expect($("a").css("text-decoration")).toBe("none");
simulateCssEvent('hover');
expect($("a").css("text-decoration")).toBe("underline");
simulateCssEvent('stop');
expect($("a").css("text-decoration")).toBe("none");
});
});