1. #1
    Membre régulier
    Profil pro
    Inscrit en
    mai 2010
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 158
    Points : 106
    Points
    106

    Par défaut Créer un objet MutationObserver

    Bonjour,

    Je cherche à créer un évènement lors de la modification d'un attribut "value" sur un champ "input" par le biais de l'objet MutationObserver.

    C'est juste un exercice de ma part autour des évènements

    Tout d'abord, est ce approprié ? Je crois que oui d'après ce que j'ai compris ici : https://developer.mozilla.org/fr/doc...tationObserver
    J'ai donc repris l'exemple ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var obs = new MutationObserver(function(MR) {
      console.log("ok");
      console.log(MR);
    });
    obs.observe(monEltHTML, {attributes: true, childList: true, characterData: true, subtree: true });
    Mais rien ne ce passe. Lorsque je modifie le champ text de mon input, cela modifie la value de l'attribut value et doit donc déclencher l'évènement non ?

    Je n'ai pas compris quelque chose, mais quoi ?

    Merci

  2. #2
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    février 2009
    Messages
    5 732
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : février 2009
    Messages : 5 732
    Points : 21 094
    Points
    21 094
    Billets dans le blog
    39

    Par défaut

    Voici l'exemple observer complet plus la génération d'un événement.

    Il suffit de copier-coller le code dans un nouveau fichier HTML pour le tester.

    Il faut cliquer sur "Press enter" avant d'appuyer sur la touche "Enter".

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    <!DOCTYPE html>
    <html lang="fr" dir="ltr">
    <head>
      <meta http-equiv="cache-control" content="public, max-age=60">
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <meta name="author" content="Daniel Hagnoul">
      <title>Test</title>
      <style>
        
      </style>
      <script>
        'use strict';
        
        document.addEventListener( 'DOMContentLoaded', ev => {
     
          
        }, false );
        
        window.addEventListener( 'load', ev => {
          
          // gestionnaire d'événement chBackColor
          document.querySelector( "main" ).addEventListener( 'chBackColor', ev => {
            ev.target.style.backgroundColor = "grey";
            
            setTimeout( () => {
              ev.target.style.backgroundColor = "white";
            }, 300 );
            
          }, false );
          
          // utilisation de MutationObserver sur le tag OL
          const
            list = document.querySelector( "#listId" ),
            observer = new MutationObserver( mutations => {
              mutations.forEach( mutation => {
                console.log( mutation.type );
                
                // action : liste les éléments de l'OL dans la console (touche F12)
                if ( mutation.type === 'childList' ){
                  let list_values = [].slice.call( list.children )
                      .map( node => node.innerHTML )
                      .filter( s => {
                        if ( s === '<br />') {
                          return false;
                        }
                        else {
                          return true;
                        }
                      });
                      
                  console.log( list_values );
                  
                  // déclencher l'événement chBackColor
                  document.querySelector( "main" ).dispatchEvent( new Event( "chBackColor" ) );
                }
              });
            }),
            config = {
              attribute : true,
              childList : true,
              characterData : true
            };
           
          observer.observe( list, config );
          
        }, false );
      </script>
    </head>
    <body>
      <main>
     
        <ol id="listId" contenteditable>
          <li>Press enter</li>
        </ol>    
     
      </main>
    </body>
    </html>

    Blog



    Nota bene : si vous devez être compatible avec les navigateurs obsolètes (IE8 et plus), vous devez convertir les codes ES2015 en ES5 avec Babel.

    FAQ JS Tutoriels JS

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    mai 2010
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 158
    Points : 106
    Points
    106

    Par défaut

    Merci pour cet exemple plus complet que sur le MDN

    Mais je ne comprend toujours pas quelques trucs :
    - Si j'observe un element input par ex. :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    <!DOCTYPE html>
    <html lang="fr" dir="ltr">
    <head>
    <meta http-equiv="cache-control" content="public, max-age=60">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" >
    <title>Test</title>
    <script>
      'use strict';
        
      document.addEventListener( 'DOMContentLoaded', ev => {}, false );
        
      window.addEventListener( 'load', ev => {
          
        // gestionnaire d'événement chBackColor
        document.querySelector( "main" ).addEventListener( 'chBackColor', ev => {
          ev.target.style.backgroundColor = "grey";
          setTimeout( () => {
            ev.target.style.backgroundColor = "white";
          }, 300 ); 
        }, false );
     
        document.querySelector("#bt").addEventListener("click", function(e){
          document.querySelector("#ipt").dataset.ok += '_ok';
        });
                     
        const 
        elt = document.querySelector( "#ipt" ),
        obs = new MutationObserver( mutations => {
          mutations.forEach( mutation => {
            console.log(mutation.type );
          })
        });
                      
        obs.observe(elt, {attribute : true, childList : true, characterData : true});
      });
    </script>
    </head>
    <body>
      <main>
        <input type="text" id="ipt" data-ok="ok"/>
        <input type="button" value="clic" id="bt"/>
      <main>
    </body>
    </html>
    Lorsque l'on click sur le bouton, la chaine "_ok" est ajoutée à la valeur de l'attribut data-ok. Je devrais donc avoir un déclenchement d'évènement non ?

    Pourtant, je ne constate aucun déclenchement...

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    mai 2010
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 158
    Points : 106
    Points
    106

    Par défaut

    Bon, je crois avoir compris. Aussi je met un exemple afin d'être sur que je ne fais pas fausse route :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const
      obs = new MutationObserver( mutations => {
        console.log(mutations);
        mutations.forEach( mutation => {
          console.log( mutation.type );
        })
      }), 
      chemin = function(path=null){
        if ( path == null ){
          return monEltHTML.value;
        }else{
          monEltHTML.value = path;
          monEltHTML.dispatchEvent( new Event( "onModified" ) );
        };
      };
     
    obs.observe(monEltHTML, {attributes: true, childList: true, characterData: true});
     
    monEltHTML.addEventListener('onModified', e=>{console.log(e);});
    Merci de vos retour

    [EDIT 1] En fait non... Je n'ai pas compris... Le code ci dessus fonctionne même si l'on retire les lignes 2 à 7 et 17, concernant l'objet new MutationObserver()... [/EDIT 1]

    [EDIT 2]
    Bon, finalement, le problème vient du fait que l'attribut value de l'element input n'est pas surveillable avec cette objet... En tout cas, si je modifie l'element input par un autre element, la solution que tu propose danielhagnoul fonctionne sans problème.
    D'ailleurs, lorsque je regarde la valeur de l'attribut value de l'element input dans l'inspecteur HTML, celui-ci ne change pas contrairement aux autres attributs... C'est un bug ou c'est normal ?
    [/EDIT 2]

  5. #5
    Membre habitué
    Femme Profil pro
    Autre
    Inscrit en
    janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : janvier 2017
    Messages : 99
    Points : 152
    Points
    152

    Par défaut

    Bonjour,
    Dans le code précédent, il manque un "s" à "attribute" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    obs.observe(elt, {attributes : true, childList : true, characterData : true});
    D'ailleurs, lorsque je regarde la valeur de l'attribut value de l'element input dans l'inspecteur HTML, celui-ci ne change pas contrairement aux autres attributs... C'est un bug ou c'est normal ?
    Je dirai "normal" et que c'est pour cela que "MutationObserver" ne se déclenche pas.
    En revanche, un "setAttribute("value","...")" devrait être détecté.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    mai 2010
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 158
    Points : 106
    Points
    106

    Par défaut

    Effectivement, si j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monElt.setAttribute("value", "ma valeur")
    cela déclenche bien le gestionnaire d'évènement.

    Si j'utilise la syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monElt.value = "ma valeur"
    Ca ne fonctionne pas... Pourtant dans les 2 cas, l'affichage du champ input est modifié.
    Piégeant comme truc.

    Quand au "s", effectivement... Mais je crois que c'est une erreur de copie du code, adapté pour ne pas être trop long.

    Merci

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    mai 2010
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2010
    Messages : 158
    Points : 106
    Points
    106

    Par défaut

    Ah si j'avais une autre question.

    sur le code suivant présenté en en 1ere reponse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    let list_values = [].slice.call( list.children )
    Pourquoi utiliser call(list.children) ?
    Est ce pour pouvoir utiliser map derriere ?
    Quelle est l'explication exacte ?

    Merci

  8. #8
    Membre habitué
    Femme Profil pro
    Autre
    Inscrit en
    janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : janvier 2017
    Messages : 99
    Points : 152
    Points
    152

    Par défaut

    Il s'agit d'obtenir une version "Array" de "list.children".
    Si "list.children" avait une méthode qui retourne un "Array" de ces éléments, on ferait directement "list.children.nomDeLaMethode()".
    Mais elle n'en a pas, donc on va prendre la méthode "slice" d'un tableau et on l'applique sur "list.children" avec "call".
    On peut aussi utiliser directement "Array.prototype.slice".

    Niveau performances, je ne sais pas si c'est très rapide, l'objectif est davantage d'avoir un code court je pense.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Travailler / Créer des objets complexes
    Par Ekinoks dans le forum OpenGL
    Réponses: 3
    Dernier message: 22/08/2005, 14h38
  2. [C#] Créer des objets Winform personnalisés
    Par KibitO dans le forum Windows Forms
    Réponses: 8
    Dernier message: 31/05/2005, 17h09
  3. [Info]Créer un objet persistent
    Par seb55555 dans le forum JDBC
    Réponses: 5
    Dernier message: 22/02/2005, 16h53
  4. [VBA ActivX] Créer un objet Name [OWC10.Spreadsheet.10]
    Par FRED.G dans le forum VBA Access
    Réponses: 12
    Dernier message: 06/07/2004, 16h29
  5. Créer des objets sur la pile ?
    Par Cornell dans le forum Langage
    Réponses: 8
    Dernier message: 03/03/2003, 11h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo