web-dev-qa-db-fra.com

Événements JS: accrochage à un événement de changement de valeur sur les entrées de texte

J'ai une entrée de texte dont le contenu est modifié par un script et non par l'utilisateur. Je voudrais donc déclencher un événement lorsque la valeur change. Je ne trouve pas d'événement approprié pour cela. J'ai même trouvé ceci sur StackOverflow , mais ce n'est pas la solution que je recherche.

Comment faire fonctionner cela avec jQuery et une entrée de texte où la valeur est définie comme ceci:

myTextControl.value = someValue

Ici, je veux déclencher un événement pour voir la nouvelle valeur.

31
Esteban Feldman

Je ne trouve pas d'événement approprié pour cela.

Ouais, il n'y en a pas.

Il y a DOM Mutation Events , mais ils ne sont pas bien pris en charge entre les navigateurs et ne se déclenchent pas pour les valeurs de formulaire de toute façon car elles ne sont pas reflétées dans les attributs (sauf dans IE en raison d'un bug).

Dans Mozilla uniquement, un JavaScript watch pourrait être défini sur la propriété value pour intercepter les modifications scriptées. Dans IE uniquement, un gestionnaire JScript onpropertychange peut être défini pour intercepter les modifications à la fois scriptées et pilotées par l'utilisateur. Dans d'autres navigateurs, vous devrez utiliser votre propre interrogateur d'intervalle pour chercher des changements.

function watchProperty(obj, name, handler) {
    if ('watch' in obj) {
        obj.watch(name, handler);
    } else if ('onpropertychange' in obj) {
        name= name.toLowerCase();
        obj.onpropertychange= function() {
            if (window.event.propertyName.toLowerCase()===name)
                handler.call(obj);
        };
    } else {
        var o= obj[name];
        setInterval(function() {
            var n= obj[name];
            if (o!==n) {
                o= n;
                handler.call(obj);
            }
        }, 200);
    }
}

watchProperty(document.getElementById('myinput'), 'value', function() {
    alert('changed!');
});

C'est très insatisfaisant. Il ne répondra pas aux modifications apportées par l'utilisateur dans Mozilla, il n'autorise qu'une seule propriété surveillée par objet dans IE, et dans d'autres navigateurs, la fonction de gestionnaire sera appelée beaucoup plus tard dans le flux d'exécution.

Il est presque certainement préférable de réécrire les parties du script qui définissent value pour appeler une fonction wrapper setValue à la place, que vous pouvez surveiller pour les modifications que vous souhaitez intercepter.

19
bobince

Vous pouvez ajouter un écouteur d'événement normal à votre champ de saisie comme ceci. (en utilisant jQuery)

$(myTextControl).change(function() {
    ...
    /* do appropriate event handling here */
    ...
});

Ok étant donné que le javascript qui modifie la valeur d'entrée n'est pas contrôlé par vous, cela devient difficile. Il vous reste deux options:

1.) Compatible Crossbrowser: implémentez l'interrogation de la valeur d'entrée avec une fonction qui vérifie en permanence si la valeur a changé. (Quelque chose dans ce sens).

//at beginning before other scripts changes the value create a global variable
var oldValue = myTextControl.value;

function checkIfValueChanged() {
    if(myTextControl.value != oldValue) {
        $(myTextControl).trigger("change");
        clearInterval(checker);
    }
}

//every 500ms check if value changed
var checker = setInterval('checkIfValueChanged()', 500);

Remarque : Si votre script ou l'utilisateur peut également modifier la valeur, vous devez implémenter quelque chose pour l'attraper afin de ne pas déclencher plusieurs fois l'événement change.

Si la valeur peut changer plusieurs fois par le script externe, laissez simplement la fonction d'intervalle s'exécuter au lieu de l'annuler et mettez à jour oldValue;

2.) AFAIK Pas encore supporté par tous les navigateurs (? Testez-le sur ceux que vous devez supporter)

Vous pouvez vous lier à un événement DOM de niveau 3 spécial: DOMAttrModified (dans Firefox, peut-être d'autres aussi je pense Opera l'a aussi, Safari ??, Chrome ??) et in = IE bien sûr, il a un nom différent propertychange (et est propriétaire et différent du comportement du W3C)

Maintenant, idéalement, vous pouvez combiner les deux options et vérifier si la prise en charge de DOMAttrModified ou propertychange est là et l'utiliser en conséquence ou utiliser la solution d'interrogation en conséquence.


Liens de lecture

Événements de mutation DOM W3C

Événement W3C DOMAttrModified

Événement de changement de propriété MSDN DHTML

Plug-in de surveillance des propriétés CSS jQuery mis à jour

Le dernier lien est un gars qui a déjà fait un plugin jQuery faisant les choses décrites par moi (non testé par moi, fourni juste comme référence)

5
jitter