IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Créer un objet MutationObserver


Sujet :

JavaScript

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 201
    Points : 150
    Points
    150
    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
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : Belgique

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

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    125
    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

    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 habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 201
    Points : 150
    Points
    150
    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 habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 201
    Points : 150
    Points
    150
    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 éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    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 : 335
    Points : 715
    Points
    715
    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 habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 201
    Points : 150
    Points
    150
    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 habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 201
    Points : 150
    Points
    150
    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 éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    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 : 335
    Points : 715
    Points
    715
    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, 15h38
  2. [C#] Créer des objets Winform personnalisés
    Par KibitO dans le forum Windows Forms
    Réponses: 8
    Dernier message: 31/05/2005, 18h09
  3. [Info]Créer un objet persistent
    Par seb55555 dans le forum JDBC
    Réponses: 5
    Dernier message: 22/02/2005, 17h53
  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, 17h29
  5. Créer des objets sur la pile ?
    Par Cornell dans le forum Langage
    Réponses: 8
    Dernier message: 03/03/2003, 12h47

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