Chrome (peut-être Safari?) déclenche" flou " deux fois sur les champs de saisie lorsque le navigateur perd le focus
Voici un jsfiddle intéressant.
Dans Firefox:
- Exécutez le violon
- Cliquez dans la saisie de texte
- Cliquez ailleurs. Devrait dire "1 brouille".
- Cliquez à nouveau dans la saisie de texte.
- ALT-TAB vers une autre fenêtre. Fiddle devrait maintenant dire "2 flous".
Dans Chrome, à l'étape 5, il est dit "3 flous". Deux événements "flou" distincts sont déclenchés lorsque le navigateur entier perd le focus. Ceci est intéressant car cela signifie qu'il n'est pas sûr de supposons, dans un gestionnaire de "flou" , que l'élément avait réellement le focus juste avant l'envoi de l'événement; c'est - à - dire que la perte de focus-la transition de "être au focus" à "ne pas être au focus" - est la raison de l'événement. Lorsque deux événements "flou" sont générés, cette condition n'est pas satisfaite lors de la gestion du second événement, car l'élément n'est déjà pas mis au point.
Alors est-ce juste un bug? Est-il possible de dire qu'un "flou" de l'événement est faux?
7 réponses
La raison pour laquelle il tire deux fois est à cause de window.onblur. Le flou de fenêtre déclenche un événement de flou sur tous les éléments de cette fenêtre dans le cadre du processus de capture/bouillonnement de javascript. Tout ce que vous devez faire est de tester la cible de l'événement pour être la fenêtre.
var blurCount = 0;
var isTargetWindow = false;
$(window).blur(function(e){
console.log(e.target);
isTargetWindow = true;
});
$(window).focus(function(){
isTargetWindow = false;
});
$('input').blur(function(e) {
if(!isTargetWindow){
$('div').text(++blurCount + ' blurs');
}
console.log(e.target);
});
Ceci est confirmé bogue Chrome. Voir le suivi des problèmes de chrome
La solution de contournement est dans la réponse acceptée.
Ce n'est probablement pas ce que vous voulez entendre, mais la seule façon de le faire semble être de suivre manuellement si l'élément est porté ou non. Par exemple (violon ici):
var blurCount = 0;
document.getElementsByTagName('input')[0].onblur = function(e) {
if (!e) e = window.event;
console.log('blur', e);
if (!(e.target || e.srcElement)['data-focused']) return;
(e.target || e.srcElement)['data-focused'] = false;
document.getElementsByTagName('div')[0].innerHTML = (++blurCount + ' blurs');
};
document.getElementsByTagName('input')[0].onfocus = function(e) {
if (!e) e = window.event;
console.log('focus', e);
(e.target || e.srcElement)['data-focused'] = true;
};
Fait intéressant, je n'ai pas pu faire fonctionner cela dans jQuery (fiddle ici)... Je n'utilise vraiment pas beaucoup jQuery, peut-être que je fais quelque chose de mal ici?
var blurCount = 0;
$('input').blur(function(e) {
console.log('blur', e);
if (!(e.target || e.srcElement)['data-focused']) return;
(e.target || e.srcElement)['data-focused'] = false;
$('div').innerHTML = (++blurCount + ' blurs');
});
$('input').focus(function(e) {
console.log('focus', e);
(e.target || e.srcElement)['data-focused'] = true;
});
Vous pouvez également essayer de comparer la cible de l'événement avec document.activeElement
. Cet exemple ignorera les événements de flou ALT + tab et le flou événements résultant de cliquer sur Chrome... chrome. Cela pourrait être utile en fonction de la situation. Si l'utilisateur alt + tabs revient dans Chrome, c'est comme si la boîte n'avait jamais perdu le focus (fiddle).
var blurCount = 0;
document.getElementsByTagName('input')[0].onblur = function(e) {
if (!e) e = window.event;
console.log('blur', e, document.activeElement, (e.target || e.srcElement));
if ((e.target || e.srcElement) == document.activeElement) return;
document.getElementsByTagName('div')[0].innerHTML = (++blurCount + ' blurs');
};
Je suis sur la version Chrome 30.0.1599.101 m sur Windows 7 et ce problème semble avoir été corrigé.
Je vis la même chose et les messages ci-dessus ont un sens quant à pourquoi. Dans mon cas, je voulais juste savoir si au moins un événement de flou s'était produit. En conséquence, j'ai trouvé que le simple retour de ma fonction de flou résolvait mon problème et empêchait l'événement suivant de se déclencher.
function handleEditGroup(id) {
var groupLabelObject = $('#' + id);
var originalText = groupLabelObject.text();
groupLabelObject.attr('contenteditable', true)
.focus().blur(function () {
$(this).removeAttr('contenteditable');
$(this).text($(this).text().substr(0, 60));
if ($(this).text() != originalText) {
alert("Change Found");
return; //<--- Added this Return.
}
});
}
On dirait qu'une bizarrerie d'angularjs donne une solution plus simple lors de l'utilisation de ng-blur; l'objet $ event n'est défini que si vous le transmettez:
ng-blur="onBlur($event)"
Donc (si vous n'utilisez pas ng-blur sur la fenêtre) vous pouvez vérifier:
$scope.onBlur = function( $event ) {
if (event != undefined) {
//this is the blur on the element
}
}