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 :

Evènements liés à la modification du DOM


Sujet :

JavaScript

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut Evènements liés à la modification du DOM
    Bonsoir à tous
    Je pense que la réponse à ma question doit se trouver quelque part dans le forum, mais je n'arrive pas à la formuler correctement e je ne parviens dont pas à trouver cette réponse.

    Voici ce dont il s'agit:

    Quand on effectue des modifications dans le DOM, par exemple lorsqu'on reçoit le résultat d'une requête AJAX et qu'on l'utilise pour générer ou modifier une partie du DOM, on n'est jamais sûr que cette modification est effectivement prise en compte.
    Dans le cas qui me préoccupe actuellement, je reçois sous forme XML une structure assez grande, et je la transforme en JS pour obtenir une <table> que j'insère dans une <div>
    Si je mets immédiatement après cette insertion une instruction qui agit sur cette <table>, elle n'est pas prise en compte.
    J'en suis réduit, faute de mieux, à lancer cette instruction par un setTimeout que j'ai expérimentalement fixé à 500ms, car les valeurs inférieures que j'ai utilisées se sont révélées insuffisantes dans certains cas.
    Il serait plus propre de déclencher cette instruction par un évènement exprimant le fait que le changement du DOM a effectivement été pris en compte.

    Existe-t-il un tel évènement, similaire à "onload"? ce n'est pas exactement de "chargement" dont il s'agit, mais conceptuellement c'est très proche

    Merci de votre aide.

  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

    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 à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut Utilisation de MutationObserver?
    Après recherches sur Internet, je trouve le concept de "MutationObserver"
    Malheureusement les exemples donnés ne sont pas très parlant: il s'agit toujours d'enregistrer dans la console des traces des modifications apportées au DOM, mais ça manque de clarté à mon goût, il y a plein de sous-entendus sur la nature des propriétés de l'objet MustationObserver, que le lecteur es sensé connaître
    Voir https://hacks.mozilla.org/2012/05/do...r-performance/
    qui est jusqu'à présent le document le plus clair que j'ai trouvé.
    Y aurait il quelque part un "MutationObserver pour les nuls"?

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Merci pour la réponse,mais mon problème n'est pas "comment utiliser AJAX", c'est un domaine où je me sens relativement confortable.
    Le problème vient après:
    Ce que je fais:
    1. je récupère une (assez grosse) structure en XML par AJAX
    2. je génère une <table> à partir de cette structure et je l'insère dans une <div> par appendChild


    Jusque là tout va bien
    Mais comme ma table est plus grande que la <div>, je voudrais scroller le résultat à un certain endroit, que j'ai noté avant de faire ma manipulation de DOM.
    C'est là que je suis obligé de mettre un setTimeout pour effectuer le scroll, car si j'écris directement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    div.appendChild(table)
    div.scrollTop = oldvalue
    ça ne fait rien du tout, il faut attendre que le DOM soit mis à jour.

    Ce que je cherche à faire, c'est d'éviter ce setTimeout dont la durée est purement expérimentale, en le remplaçant par quelque chose du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    div.addEventListener("domReady", fonction-de-scroll)
    Je cherche donc si un évènement de type "domReady" existe.
    Comme je l'ai dit dans mon message précédent, il semble que cela nous amène à utiliser MutationObserver, et là je suis comme une poule qui a trouvé un couteau...

  5. #5
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Bonjour,
    je voudrais scroller le résultat à un certain endroit, que j'ai noté avant de faire ma manipulation de DOM.
    comment est déterminé cet endroit, appartient-il à la table ?

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Désolé de n'avoir pas répondu plus tôt, je n'étais pas disponible ces derniers jours.
    Bien entendu que cet endroit appartient à la table, mais ce n'est pas le point qui me préoccupe, je pense que je ne me suis pas bien expliqué.
    Le point que j'essaie d'aborder, c'est l'utilisation pratique de MutationObserver, qui vient remplacer les anciens évènements que j'aurais voulu utiliser, mais qui sont obsolètes.
    On trouve très peu d'information sur ce sujet, et de plus ce sont des informations qui récapitulent ce que savent ceux qui savent, et non pas des informations à destination de ceux qui ne savent pas...

  7. #7
    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,
    Mais comme ma table est plus grande que la <div>, je voudrais scroller le résultat à un certain endroit, que j'ai noté avant de faire ma manipulation de DOM.
    Il me semble que ce devrait être immédiatement possible.
    Voici un brouillon, avec au passage un exemple d'utilisation de MutationObserver (il suffit de reprendre l'exemple ici : https://developer.mozilla.org/fr/doc...tationObserver) :
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <div id="contTabl" style="max-height:200px;overflow:auto;"></div>
    <script>
    var xhr_;
     
    (xhr_=new XMLHttpRequest()).onreadystatechange=function(ev_)
    	{
    	if(this.readyState===XMLHttpRequest.DONE)
    		{
    		var ob_contTablHtml;
    		var ob_obseMuta;
    		var ob_tablHtml;
     
    		(ob_obseMuta=new MutationObserver(function(ar_)
    			{
    //			ob_contTablHtml.scrollTop=200;
    			ar_.forEach(function(ob_)
    				{
    				console.log(ob_.type);
    				});
    			})).observe(ob_tablHtml=document.createElement("table"),{childList:true});
    		ob_tablHtml.innerHTML=this.responseText;
    		(ob_contTablHtml=document.getElementById("contTabl")).appendChild(ob_tablHtml);
    		ob_contTablHtml.scrollTop=100;
    		}
    	};
    xhr_.open("GET","contenu.php",true);
    xhr_.send();
    </script>
    Fichier php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?php
    $i=0;
    while(++$i<101)
            {
            echo '<tr><td>'.$i.'</td></tr>';
            }
    ?>

  8. #8
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Je reviens sur ton problème de scroll après modification du DOM d'un de tes éléments
    C'est là que je suis obligé de mettre un setTimeout pour effectuer le scroll, car si j'écris directement...
    Comme il s'agit de scroller vers un élément de ta <table> fraichement constituée, si tu peux mettre une ancre sur cet élément, il te suffit d'utiliser la méthode scrollIntoView() pour que cet élément apparaisse en tête.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Bien entendu, c'est ce que j'ai commencé par faire, mais ce n'est pas très élégant.
    Il faut d'abord déterminer quel est l'élément de la <table> c'est à dire la balise <tr> que je veux mette en tête, ce qui n'est pas toujours très simple, alors qu'enregistrer quelle est la valeur de scrollTop avant la génération de la table et donner la même valeur après la génération est immédiat.
    Par ailleurs, si on veut faire des applications basées sur AJAX, il semble indispensable de disposer de l'équivalent de l'évènement "onload".
    C'est pour cela que je me suis orienté vers le traitement des "évènements DOMDocument", et que j'ai découvert dans la documentation que ceux qu'on avait primitivement définis étaient obsolètes et devaient être remplacés par MutationObserver.
    La logique de MutationObserver est nettement différente de celle des évènements: on définit d'abord un objet MutationObserver en lui fournissant une fonction, et on lance et arrête le fonctionnement de cet objet sur un élément du DOM, ce qui permet de récupérer tous les évènements qui ont affecté cet élément.
    Ce que je cherche à comprendre c'est comment mettre cela en pratique, en commençant par cet exemple simple, avec comme objectif d'en apprendre plus et d'utiliser ce mécanisme dans d'autres contextes.

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Loralina Voir le message
    Bonjour,
    Il me semble que ce devrait être immédiatement possible.
    Voici un brouillon, avec au passage un exemple d'utilisation de MutationObserver (il suffit de reprendre l'exemple ici : https://developer.mozilla.org/fr/doc...tationObserver) :
    Merci de ta réponse
    C'est bien cette page que j'avais lue (et d'autres du même genre) et que je qualifie de "couteau" pour la poule que je suis!

    Sauf erreur, j'ai bien compris le principe (voir mon explication dans mon message précédent, dites moi si j'ai compris de travers)
    mais l'exemple donné dans cette page ne m'a pas permis de me faire une idée de la façon de remplacer effectivement les évènements DOM par cet outil.
    La seule chose qu'on fasse dans cette fonction d'observation, c'est noter la progression des évènements dans la console, ce qui n'est pas très intéressant en soi. Je voudrais non pas "observer" mais "agir", être alerté quand c'est prêt.... bref je voudrais un gestionnaire d'évènement similaire à "onload", qui déclenche une action sur "onDOMElementReady". Je vois vaguement que c'est faisable par cette approche, mais un mode d'emploi pratique serait bienvenu. A mon âge, on est dur de la comprenette

  11. #11
    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,
    être alerté quand c'est prêt....
    C'est le cas dans la mesure où la fonction n'est pas appelée à chaque appendChild du script en cours mais bien une seule fois, après l'exécution du script.
    Un exemple qui le montre :
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <div id="contTabl" style="max-height:200px;overflow:auto;"></div>
    <script>
    var xhr_;
     
    (xhr_=new XMLHttpRequest()).onreadystatechange=function(ev_)
    	{
    	if(this.readyState===XMLHttpRequest.DONE)
    		{
    		var ar_st_lign;
    		var i;
    		var j;
    		var ob_contTablHtml;
    		var ob_obseMuta;
    		var ob_tablHtml;
    		var ob_lignTablHtml;
     
    		j=0;
    		(ob_obseMuta=new MutationObserver(function(ar_,ob_)
    			{
    			console.log("appel",++j); //un seul appel
    			ob_contTablHtml.scrollTop=200;
    /*			ar_.forEach(function(ob_)
    				{
    				console.log(ob_); //100 appels, 1 pour chaque ligne ajoutée
    				});*/
    			})).observe(ob_tablHtml=document.createElement("table"),{childList:true});
    		for(i in ar_st_lign=this.responseText.split(","))
    			{
    			(ob_lignTablHtml=document.createElement("tr")).innerHTML="<td>"+ar_st_lign[i]+"</td>";
    			ob_tablHtml.appendChild(ob_lignTablHtml);
    			}
    		(ob_contTablHtml=document.getElementById("contTabl")).appendChild(ob_tablHtml);
    		ob_contTablHtml.scrollTop=100;
    		console.log("exécuté avant MutationObserver");
    		}
    	};
    xhr_.open("GET","contenu.php",true);
    xhr_.send();
    </script>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <?php
    $i=0;
    while(++$i<100)
            {
            echo 'ligne '.$i.',';
            }
    echo 'ligne '.$i;
    ?>
    Après, comme je disais, je pense qu'il ne devrait pas y avoir besoin de MutationObserver.
    Dans mon test, on voit que scrollTop est modifiable sans délai.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Loralina Voir le message
    Après, comme je disais, je pense qu'il ne devrait pas y avoir besoin de MutationObserver.
    Dans mon test, on voit que scrollTop est modifiable sans délai.
    J'ai mis un peu de temps à comprendre le code de ce test, que je retranscris d'une façon légèrement différente, qui correspond à mon style de programmation, dis moi si je n'ai pas raté quelque chose:
    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
    20
    21
    22
    23
    <div id="contTabl" style="max-height:200px;overflow:auto;"></div>
    <script>
    var xhr_= new XMLHttpRequest();
    xhr_.onreadystatechange = function() {
    	if(this.readyState === XMLHttpRequest.DONE) {
     
    		var j = 0, ob_obseMuta = new MutationObserver(function(ar_,ob_) {console.log("appel",++j)};
                    var ob_tablHtml  = document.createElement('table');
    		ob_obseMuta.observe(ob_tablHtml, {childList:true});
     
    		var arrayLines = this.responseText.split(',');
    		for(var i = 0; i < arrayLines.length; i++) {
    			var arrayLine = document.createElement('tr');
    			arrayLine.innerHTML = '<td>' + arraylines[i] + '</td>';
    			ob_tablHtml.appendChild(arrayLine);
    		}
                   var  ob_contTablHtml = document.getElementById("contTabl");
                   ob_contTablHtml.appendChild(ob_tablHtml);
    	       ob_contTablHtml.scrollTop=100;
    	}
    xhr_.open("GET", "contenu.php", true);
    xhr_.send();
    </script>
    Tout ce qui tourne autour de MutationObserver ne sert qu'à écrire dans la console, donc éventuellement à faire de la mise au point, mais pour le reste ça me semble totalement inutile.

    Je soupçonne que la raison pour laquelle j'ai besoin d'un timer, c'est que mon programme est un peu plus compliqué que cela:
    1) je ne récupère pas du texte, mais un DOMDocument XML
    2) à partir de ce DOMDocument je génère une foultitude d'objets
    3) à partir de ces objets, je génère la <table> et son contenu, avec des addEventListener sur de nombreux éléments contenus dans la <table>
    C'est sans doute cette complexité qui prend du temps.

    Mais je n'ai toujours pas compris comment utiliser MutationOberver pour faire quelque chose d'utile.

  13. #13
    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
    Je vois 3 erreurs dans ce script :
    - Ligne 7 : il manque une parenthèse fermante.
    - Ligne 14 : il manque la majuscule au "l" de "arraylines" : "arrayLines".
    - Après la ligne 20 : il manque une accolade fermante.

    Tout ce qui tourne autour de MutationObserver ne sert qu'à écrire dans la console, donc éventuellement à faire de la mise au point, mais pour le reste ça me semble totalement inutile.
    Dans le cas présent, je pense que son utilisation n'est pas requise, même si on peut définir scrollTop à ce niveau.

    C'est sans doute cette complexité qui prend du temps.
    Ce n'est pour moi pas une question de temps, mais plutôt de script en cours.

    Ce qui me paraît important, c'est de définir scrollTop une fois le tableau rempli (s'il y a des images, je suppose qu'il est préférable aussi d'attendre qu'elles soient chargées si leurs dimensions ne sont pas spécifiées).

    Par exemple, si un script prend 10 secondes et que pendant le script le tableau est bien rempli, alors un scrollTop à la fin de ce script fonctionnera.
    Par contre, si le script dure 1 milliseconde, mais qu'il est différé avec un setTimeout, lancé à 0 ms par exemple, alors un scrollTop à la fin du script effectuant le setTimeout sera sans effet.

    3) à partir de ces objets, je génère la <table> et son contenu, avec des addEventListener sur de nombreux éléments contenus dans la <table>
    Il est possible que tout ou partie du contenu du tableau ne soit pas créé durant le script en cours, mais seulement après un délai en lien avec des addEventListener, ou en lien avec des images en attente de chargement, ou autre chose encore.
    Cela expliquerait pourquoi scrollTop ne fonctionne pas (enfin, ce n'est pas vraiment qu'il ne fonctionne pas, mais plus probablement qu'il n'y a pas encore assez de hauteur au tableau).

    Si le tableau est rempli en plusieurs étapes (plusieurs scripts indépendants, je ne veux pas juste dire des fonctions séparées), il reste à déterminer quelle étape est la dernière pour définir scrollTop à la fin de cette étape.
    Eventuellement, avec un compteur, on doit pouvoir s'en sortir.

  14. #14
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Je ne reviendrais pas sur les points soulevés par Loralina, qui sont tous judicieux, mais uniquement sur
    Mais je n'ai toujours pas compris comment utiliser MutationOberver pour faire quelque chose d'utile.
    Lorsque tu crées un objet MutationObserver ce constructeur à besoin d'une fonction de rappel qu’il utilise pour nous informer des « mutations » et c'est dans celle ci que tu mets ce que tu veux faire quand la « mutation » est atteinte.

    Ensuite on le place, via la méthode observe, sur le nœud que l'on souhaite surveiller en lui indiquant ce sur quoi on veux être informé, dans ton cas l'ajout d'un élément (childList: true pour surveiller les ajouts et suppressions d'éléments)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var oDest = document.querySelector('#result');
     
    var observer = new MutationObserver( function (arg) {
      var oThis = arg[0].target;     // l'objet surveillé
      oThis.scrollTop = 500;         // l'action à réaliser
    });
     
    observer.observe(oDest, {
      childList: true
    });
     
    fonctionTresLongue();

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Merci pour la réponse
    Citation Envoyé par Loralina Voir le message
    Je vois 3 erreurs dans ce script :
    - Ligne 7 : il manque une parenthèse fermante.
    - Ligne 14 : il manque la majuscule au "l" de "arraylines" : "arrayLines".
    - Après la ligne 20 : il manque une accolade fermante.
    C'est tout à fait exact, je n'ai fait que "retranscrire" le script à ma sauce, je n'ai pas tenté de l'utiliser.
    Je voulais simplement comprendre le fonctionnement du script originel, car la façon dont il est écrit ne correspond pas à mon style de programmation et la lecture de chaque ligne me pose un problème de compréhension

    Citation Envoyé par Loralina Voir le message
    Dans le cas présent, je pense que son utilisation n'est pas requise, même si on peut définir scrollTop à ce niveau.
    ...
    Éventuellement, avec un compteur, on doit pouvoir s'en sortir.
    Je ne veux pas "m'en sortir", ça, j'y suis parvenu avec un timer, et ça me donne le résultat cherché.

    Quelle que soit la raison, je constate factuellement que si je fais certaines actions sur un élément généré dynamiquement, ces actions entrent d'une certaine façon en conflit avec la prise en compte des modifications du DOM par le navigateur.

    Par exemple, j'ai un autre cas dans lequel on veut modifier le texte d'un élément, et plutôt que de mettre cet élément en "contenteditable", j'ai préféré générer une <input type="text"> qui vient se superposer au texte de l'élément, avec un addEventListener approprié.
    Une fois cette <input> générée, la chose à faire est de lui donner le focus pour que l'utilisateur puisse immédiatement y entrer un texte.
    J'ai constaté que je devais mettre un timer avant de donner le focus, sinon il ne se passe rien, c'est à dire que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    element1.appendChild(element2);
    element2.focus();
    ne fonctionne pas, il faut mettre un timeout de 100ms pour que le focus soit effectivement mis sur ce nouvel élément.

    Tout cela, c'est du contournement.
    S'il y avait un évènement "onDOMElementReady", ce serait nettement préférable, et je n'aurais pas besoin de faire de l'informatique expérimentale

    Puisque les évènements sur modification du DOM sont obsolètes et que la doc dit d'utiliser MutationObserver, va pour MutationObserver... à condition de comprendre comment ça marche.

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    J'ai poursuivi mes recherches de documents parlant de MutationObserver.
    La plupart de ces documents sont aussi peu intéressant que l'article de mozilla, les fonctions invoquées étant toujours des console.log qui n'apprennent rien sur la façon dont on utilise pratiquement MutationObserver
    Je viens de trouver un document qui me donne l'impression d'être un peu plus utilisable, même si je ne l'ai pas encore décortiqué en détail
    http://ryanmorr.com/using-mutation-o...-availability/
    La suite quand je l'aurai lu, compris, assimilé...

  17. #17
    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
    Bonsoir,
    Pour MutationObserver, je pense que NoSmoking a bien expliqué : dans la fonction qui est appelée suite aux modifications du tableau, on code ce que l'on veut, exemple : on y définit scrollTop.
    Même si le tableau est rempli en plusieurs étapes (sous-entendu qu'il y aurait une interruption après chaque étape), chaque étape devrait être suivie d'un appel à cette fonction et le scrollTop devrait finir par être bien positionné à la dernière étape.

    Pour le champ, il faut voir également si c'est réellement un problème de "DOM" pas prêt ou si ce n'est pas plutôt lié à une perte de focus.
    Exemple :
    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
    <div onmousedown="modifier(this);">texte à modifier</div>
    <div onclick="modifier(this);">texte à modifier</div>
    <script>
    function modifier(ob_)
    	{
    	var ob_cham;
     
    	console.log(document.activeElement);
    	ob_.appendChild(ob_cham=document.createElement('input'));
    	ob_cham.onblur=function(){if(this.value!=="") {this.parentNode.innerHTML=this.value;}};
    	ob_cham.focus();
    	console.log(document.activeElement); //vaut bien le champ
    	setTimeout(function(){console.log(document.activeElement);},0); //sur Firefox : focus perdu avec onmousedown, maintenu avec onclick
    	}
    </script>
    On voit ici qu'il s'agit bien d'une perte de focus (sans doute liée au clic toujours enfoncé).

    Il faudrait voir un exemple de cas mettant en évidence que ce peut être lié au "DOM" qui n'est pas prêt.
    De même pour le scrollTop du tableau, il serait bien d'avoir un exemple fonctionnel d'un cas qui montre que c'est lié au "DOM" pas prêt.
    Avec de tels exemples, si MutationObserver s'avère requis, ce sera plus simple pour montrer comment l'intégrer.

  18. #18
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    ...
    Merci, voilà quelque chose qui me semble plus clair que tous les exemples que j'ai pu trouver par ailleurs.

    En d'autres termes, alors que pour un évènement on attache le traitement de l'évènement à un élément et c'est tout, je comprends que cette techno consiste
    1) à créer un objet "observeur" en y mettant la fonction sui nous intéresse sans préciser à quel élément ça va s'appliquer, mais en ayant en tête tout de même de quel élément ou de quelle "famille' d'éléments il s'agit
    2) à faire "observer" par cette fonction ce qui se passe pour l'élément qui nous intéresse
    C'est assez déroutant...

    Je ferai des essais demain dans cette direction, il est trop tard pour que je m'y mette ce soir.

    Merci en tous cas à tous deux pour votre aide précieuse!

  19. #19
    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,
    Je reviens sur ma conclusion :
    On voit ici qu'il s'agit bien d'une perte de focus (sans doute liée au clic toujours enfoncé).
    J'ai refait un test, c'est bien une perte de focus, mais qui n'est pas liée au clic toujours enfoncé : cela vient du fait que, dans la fonction liée à onmousedown, le focus n'est pas encore défini sur l'élément cliqué, il ne l'est qu'après coup et c'est cela qui fait perdre le focus au champ créé sur Firefox :
    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
    20
    21
    22
    23
    <input onmousedown="test(this);">
    <input onclick="test2(this);">
    <script>
    function test(ob_)
    	{
    	var ob_cham;
     
    	console.log(document.activeElement); //le focus n'est pas encore sur le champ cliqué
    	ob_.parentNode.appendChild(ob_cham=document.createElement('input'));
    	ob_cham.focus();
    	console.log(document.activeElement); //vaut bien le nouveau champ
    	setTimeout(function()
    		{
    		console.log(document.activeElement); //Firefox : champ cliqué, Internet Explorer : nouveau champ
    		ob_cham.focus();
    		console.log(document.activeElement); //nouveau champ
    		},0);
    	}
    function test2(ob_)
    	{
    	console.log(document.activeElement); //champ cliqué
    	}
    </script>
    J'ajoute (9h59) : pour le test précédent avec la balise div, le principe est similaire, même si le focus n'est pas donné précisément à la balise.

    Pour le tableau, j'ai mis 100000 lignes, 3 colonnes, l'affichage prend plusieurs secondes, scrollTop fonctionne comme prévu en fin de script.
    La lourdeur de l'affichage n'implique donc pas, pour ce test, la nécessité d'une étape supplémentaire requise par le navigateur pour que le "DOM" soit prêt, il l'est déjà en fin de script.

    Si le remplissement du tableau est effectué en plusieurs étapes, alors il devrait suffire de modifier scrollTop à la fin de la dernière étape.
    MutationObserver peut éventuellement convenir dans la mesure où il devrait se déclencher après la dernière étape.
    Cela dit, son utilisation n'est pas forcément requise, il faudrait établir qu'il y a bien des cas où le "DOM" n'est prêt que dans un second temps.

    A noter que dans les options de MutationObserver, il peut être utile d'ajouter subtree:true, dans le cas où les lignes ou les cellules ne sont pas remplies tout de suite.

  20. #20
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 26
    Points : 10
    Points
    10
    Par défaut
    Merci Loralina

    Je viens de passer de nombreux mois à migrer un site à l'ancienne vers quelque chose de "responsive" (pour les appareils mobiles) et qui marche tout de même sur les anciennes versions des navigateur (pour les habitués du site)
    Cela m'a obligé à faire des contournements, et finalement à ne pas utiliser de fonctions un peu touchy.
    L'application sur laquelle je travaille maintenant est une application d'administration du site, ce qui me permet de ne pas trop me préoccuper des compatibilités entre navigateurs: je n'ai besoin de supporter que les dernières versions de Chrome et FireFox, donc je peux un peu tester de nouvelles fonctionnalités.
    Citation Envoyé par Loralina Voir le message
    Bonjour,
    Je reviens sur ma conclusion :
    J'ai refait un test, c'est bien une perte de focus, mais qui n'est pas liée au clic toujours enfoncé : cela vient du fait que, dans la fonction liée à onmousedown, le focus n'est pas encore défini sur l'élément cliqué, il ne l'est qu'après coup et c'est cela qui fait perdre le focus au champ créé sur Firefox
    C'est un phénomène intéressant: le script donne bien le focus à l'élément créé, mais comme le script a démarré avant que le focus soit mis sur l'élément en cours, le focus est mis sur l'élément en cours après l'exécution du script!!!
    Je pensais éviter ce genre de problème en lançant le script sur onclick, qui est habituellement le dernier évènement qui se manifeste, je n'avais pas pensé que onfocus se produit, d'une façon assez logique, après le onclick.
    Je vais essayer de lancer le script sur onfocus, on verra bien.

    Pour MutationObserver, mes pratiques de programmation font que je fais pratiquement toujours les choses en 2 temps:
    1) générer un élément du DOM (en l'occurrence la table) complètement
    2) l'ajouter ensuite dans son conteneur
    Dans ces conditions, je pense que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    observer.observe(container, {childList: true});
    devrait être suffisant.
    Là aussi, on verra bien lors des test.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/12/2015, 13h02
  2. Gestion des objets liés à un element du DOM
    Par RapotOR dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/02/2010, 13h28
  3. [DOM] Surveiller une modification du DOM (lib prototype)
    Par Cladjidane dans le forum Bibliothèques & Frameworks
    Réponses: 9
    Dernier message: 04/02/2008, 14h58
  4. [DOM] Modification du DOM non visible lors d'un setInterval
    Par Mr N. dans le forum Général JavaScript
    Réponses: 10
    Dernier message: 02/11/2007, 14h36
  5. [DOM] Modification du DOM d'une popup
    Par Mike_69 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 28/03/2007, 13h28

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