Précédent   Forum des professionnels en informatique > Webmasters - Développement Web > Contribuez
Contribuez Proposez vos articles, cours, tutoriels, questions/réponses pour les FAQ, sources et autres ressources pour la rubrique Web ainsi que ses sous-rubriques.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 20/06/2007, 22h55   #1
Inactif
 
Avatar de Hibou57
 
Inscription : mars 2006
Messages : 852
Détails du profil
Informations forums :
Inscription : mars 2006
Messages : 852
Points : 398
Points : 398
Par défaut [DOM] nodeValue et firstChild pour initialisation de contenu texte

Bonsoir

Encore un topic/truc pour débutant(e) :

Context : Soit un paragraphe, que nous appelerons messageArea, dans un document HTML, pour lequel le contenu texte est déterminé à l'execution, et fixé par une procedure JavaScript.

Ce qui viens d'abord à l'esprit est
Code html :
1
2
 
   <p id="messageArea"></p>
pour l'HTML, puis
Code javascript :
1
2
3
4
 
   text = xxxx; // compute anything you want here
   messageArea = document.getElementById('messageArea');
   messageArea.firstChild.nodeValue = text; // <- Erreur d'execution
pour le code JavaScript.

Ca a l'air beau, mais ça ne marche pas

Zut, pourquoi ?

Raison : Dans le code HTML, aucun texte n'est donné pour l'élément P : normal, puisque notre texte est determiné à l'execution. Ors, pour donner une valeur à un noeud texte, il faut un noeud texte (ça va de soi). Ce noeud texte n'existe pas, puisque l'élément P ne contient rien, et donc l'invocation de firstChild produit une erreur, car le navigateur ne cré pas toujours de noeud texte par défaut vide (Internet Explorer ne le fait pas, par raison d'économie).

Solution : Le noeud texte ne peut pas être implicite, il faudra donc rendre sont existence explicite. Même si le contenu effectif n'est déterminé qu'à l'execution, il faut donner une valeur à l'élément P, dans le document HTML, pour que le DOM contienne un noeud texte à cet endroit là. On pourra utiliser simplement trois petit point par exemple ("..."). Ces trois petits points conviennent parfaitement à quelque choses qui ne connaitra qu'un bref instant d'affichage, avant d'être initialisé.

Il faut alors simplement remplacer le code HTML par
Code html :
1
2
 
   <p id="messageArea">...</p>
Le code JavaScript n'est pas en cause dans cette erreur, et il n'y a pas besoin de le modifier.

Moralité : dans vos documents HTML, destinés à êtres utilisés pour du DHTML, initialisez toujours vos noeuds texte, même si leurs valeurs effectives ne sont determinés qu'à l'execution du programme JavaScript.

Détail subsidiaire : nous employons messageArea.firstChild.nodeValue, et non pas simplement messageArea.nodeValue, parce que le contenu texte est en fait un noeud enfant... anonyme... mais un noeud enfant quand-même.
Hibou57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 08h03   #2
Expert Confirmé
 
Avatar de javatwister
 
Homme
danseur
Inscription : août 2003
Messages : 2 667
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Calvados (Basse Normandie)

Informations professionnelles :
Activité : danseur

Informations forums :
Inscription : août 2003
Messages : 2 667
Points : 3 035
Points : 3 035
mais pour initialiser la zone dès le chargement, autant créer le paragraphe et son textNode dans la foulée...;
javatwister est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 09h02   #3
Rédacteur/Modérateur
 
Avatar de SpaceFrog
 
Homme
Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Inscription : mars 2002
Messages : 30 120
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Royaume-Uni

Informations professionnelles :
Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Secteur : Industrie

Informations forums :
Inscription : mars 2002
Messages : 30 120
Points : 45 283
Points : 45 283
Code :
1
2
3
4
5
6
7
8
9
function popul(){
var text = ' xxxx '; // compute anything you want here
var    messageArea = document.getElementById('messageArea');
messageArea.firstChild.nodeValue = text; // <- Erreur d'execution
 }
</script>
</head>
 
<body onload='popul()'>
ceci fonctionne sans aucun souci chez moi sous IE et FFX

aussi avec firstChild.data...


à une condition
mettre au minimum un contenu au départ dans la balise
sinon il n'a pas de firstChild ...
Code :
<p id="messageArea">.</p>
ou alors le créer dynamiquement et l'appender à la balise
ce qui se fait en général en une seul étape comme le suggère JT:

Code :
 messageArea.appendChild(document.createTextNode(text))}
et du coup la balise peut être vide
__________________
Ma page Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag


réalisations :www.planet-languages.com|www.saftair.com| www.ouestisol.fr | www.sebemex.fr | www.extramiante.fr | www.sistac-alizay.fr | www.acoustishop.fr | www.litt.fr | www.ouestventil.fr
SpaceFrog est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 13h51   #4
Inactif
 
Avatar de Hibou57
 
Inscription : mars 2006
Messages : 852
Détails du profil
Informations forums :
Inscription : mars 2006
Messages : 852
Points : 398
Points : 398
Citation:
Envoyé par SpaceFrog
à une condition
mettre au minimum un contenu au départ dans la balise
sinon il n'a pas de firstChild ...
SpaceFrog.... c'est exactement ce que disait le post justement (c'était un post pour aider les débutant-e-s en DHTML... come moi ... quand je fais une erreure, je la résoud, et j'en parle ici)

La deuxième solution que tu propose, basée sur appendChild, ne convient pas au cas où l'espace messageArea est modifié plusieurs fois au cours de la vie de la page. Ou alors il faut tester la présence ou non du noeud anonyme. Ne pas avoir à le faire est une petit allégement, et en sus de cela, plus loin, nous verrons pourquoi il est important d'avoir un contenu initial, pour des raisons même autre encore que celle de seulement permettre par là d'avoir un noeud initial.

Citation:
Envoyé par JavaTwister
mais pour initialiser la zone dès le chargement, autant créer le paragraphe et son textNode dans la foulée...;
Pardon JavaTwister, tu fais erreur, mais au moins ton intervention at-elle le mérite de montrer le mauvais exemple à ne pas suivre (je te taquine ).

Pourquoi : parce que le design JavaScript doit être conçu à la manière du design CSS, c'est-à-dire en séparant la structure et le comportement, de même que CSS sépare le contenu et la présentation.

Ainsi, pour cette raison, aucun code JavaScript ne doit être inclus dans les pages (dans l'idéal), peut-être à l'exception notable des code AdSense et autres régie de diffusion publicitaire.

Séparer le contenu et le comportement.
Pour utiliser JavaScript, et faire du DHTML propre, en séparant proprement la structure du document et son comportement (document behaviour), il faut seulement donner des attributs id au élément concerné par un comportement quelquonque, puis dans la procédure d'initialisation, attaché les comportement à chaque élément de l'id correspondant (par exemple associer la procédure newDocument à l'élément qui a l'id newDocumentButton)

Mais me direz-vous, il faut bien pourtant un petit bout de code, ne serait-ce que pour attacher un handler d'événement onload à l'élément body, pour que cette initialisation puisse se faire.

Hé bien non, même pas Il ne suffit que d'une balise script dans l'entête HTML, avec l'URL du fichier JavaScript. Ce fichier JavaScript contient cette ligne

Pour mapage.html :
Code html :
1
2
3
4
5
6
 
<head>
   <!-- ... -->
   <script type="text/javascript" src="monprograme.js"></script>
   <!-- ... -->
</head>
Attention à la balise SCRIPT fermante qui est obligatoire, même si nous n'avons pas de contenu, et seulement des attributs (du moins en HTML, car en XHTML, on peut faire <script ... />, mais je conseil toujours le HTML 4 strict avec éventuellement iframe - en guise d'entorse - plutôt que le XHTML... ceci étant une autre affaire, je ne m'en justifierai pas dans ce fil)

Pour monprograme.js :
Code javascript :
1
2
3
4
 
/* ... */
window.onload = init; /* init, ou tout autre nom */
/* ... */
Attention à la casse de onload : n'écrivez surtout pas onLoad

Mauvais exemple :
Code html :
1
2
 
   <body onload="init"> <!-- pas bien -->

Code html :
1
2
 
   <body onload="if (truc) chose (); machin (); ..."> <!-- encore pire -->

Si vous suivez le mauvais exemple, vous n'aurez pas de sucette. Nah!

Le code qui figure dans le fichier *.js, en dehors de tout corp de fonction, est considéré un peu comme le code contenu entre le BEGIN ... END. d'un programe Pascal ou dans le main d'un programme C

Il n'y a plus nécéssité d'inclure le moindre bout de code dans le HTML, et il ne reste plus qu'un lien vers le ou les fichiers JavaScript (il peut y en avoir plusieurs, si l'application est complexe, il est plus aisé de répartire les fonctionnalités sur divers fichiers)

Note : ceci m'a été inspiré par un article sur le site Pompage (mais j'ai perdu l'URL de la page, sorry, I'm so sorry )

Quel contenu initial ?
Comme dit dans le topic, et comme rappelé par SpaceFrog, il faut un contenu initial, sinon firstChild n'existe pas. Mais alors quel contenu initial choisir ? Si le contenu initial n'est pas important (il ne s'affiche que transitoirement), il peut être les simples trois petits points dont je parlais. Mais on pourra aussi préférer, surtout si la page doit être référencer par les moteurs de recherche, initialisé avec une petite phrase décrivant le contenu variable (une sorte de de phrase décrivant l'aspect du contenu générique), car les robots d'exploration n'execute que trés rarement le JavaScript.

Il va de soit, que non seulement cette solution a le mérite de la séparation du contenu et du comportement, mais en plus, elle offre donc un contenu directement utilisable par les robots, ce que ne fait pas la solution d'intégré un code JavaScript d'initialisation du contenu directement dans le code HTML. Car pour les robots, le contenu initial est alors vide, et n'est absolument pas interprétable.

Il n'y a que du bon à appliquer cette règle de la séparation

Pourquoi séparer le contenu et le comportement ?
Réponse : parce que c'est plus crawler-friendly, et même aussi plus user-friendly dans certaines conditions (mais la première raison domine largement). De plus, le code ainsi séparé est plus lisible et plus facile à maintenir (car plus clair, moins brouillon et moins embrouillé), et si vous travailler en équipe, avec répartition des tâche, la personne en charge du HTML n'aura pas à bricoler avec le JavaScript, mais seulement avec des attributs id. Il sera possible, aprés s'être entendu sur les élément et leurs id (on l'aura fait en phase de design ou de spécification), de travailler alors chacun sur sa tâche, sans se marcher sur les pieds ni se nuire mutuellement (éditer un fichier à deux en même temps, n'est pas trés recommendable).


N.b. Je ne sais pas si j'ai bien fait de répondre ça ici , j'aurais peut-être dut ouvrir un topic exprêt, ... une autre note pour débutant-e ... je laisse à la modération le choix de déplacer ce post, si elle le juge pertinant.
Hibou57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 17h17   #5
Expert Confirmé
 
Avatar de javatwister
 
Homme
danseur
Inscription : août 2003
Messages : 2 667
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Calvados (Basse Normandie)

Informations professionnelles :
Activité : danseur

Informations forums :
Inscription : août 2003
Messages : 2 667
Points : 3 035
Points : 3 035
écoute, c'est proprement phénoménal ce que je viens d'apprendre, là; je suis trop vieux, je vais démissionner
javatwister est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 17h21   #6
Rédacteur/Modérateur
 
Avatar de SpaceFrog
 
Homme
Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Inscription : mars 2002
Messages : 30 120
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Royaume-Uni

Informations professionnelles :
Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Secteur : Industrie

Informations forums :
Inscription : mars 2002
Messages : 30 120
Points : 45 283
Points : 45 283
sans doute un universitaire ?
c'est pour une thèse ... ?
__________________
Ma page Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag


réalisations :www.planet-languages.com|www.saftair.com| www.ouestisol.fr | www.sebemex.fr | www.extramiante.fr | www.sistac-alizay.fr | www.acoustishop.fr | www.litt.fr | www.ouestventil.fr
SpaceFrog est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 17h35   #7
Expert Confirmé
 
Avatar de javatwister
 
Homme
danseur
Inscription : août 2003
Messages : 2 667
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Calvados (Basse Normandie)

Informations professionnelles :
Activité : danseur

Informations forums :
Inscription : août 2003
Messages : 2 667
Points : 3 035
Points : 3 035
en tout cas, c'est tout bien dit: bravo;
javatwister est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/06/2007, 18h41   #8
Rédacteur/Modérateur
 
Avatar de SpaceFrog
 
Homme
Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Inscription : mars 2002
Messages : 30 120
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Royaume-Uni

Informations professionnelles :
Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Analyste Programmeur
Secteur : Industrie

Informations forums :
Inscription : mars 2002
Messages : 30 120
Points : 45 283
Points : 45 283
Mais alors du coup ça relève plius de la contribution ...

Je déplace alors
__________________
Ma page Developpez
Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
Votre post est résolu ? Alors n'oubliez pas le Tag


réalisations :www.planet-languages.com|www.saftair.com| www.ouestisol.fr | www.sebemex.fr | www.extramiante.fr | www.sistac-alizay.fr | www.acoustishop.fr | www.litt.fr | www.ouestventil.fr
SpaceFrog est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 09h51   #9
Expert Confirmé Sénior
 
Avatar de Auteur
 
Inscription : avril 2004
Messages : 4 796
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : avril 2004
Messages : 4 796
Points : 5 119
Points : 5 119
En ce qui me concerne :
  • si je dois ajouter dans ma page un élément (div, a, img, span, form, select, p, table, etc...), j'utilise les fonctions DOM :
    • createElement()
    • appendChild(), insertBefore()
    • removeChild()
  • par contre, je dois l'avouer , si je dois insérer un texte non formaté dans une balise vide (p, div, span, td), j'utilise volontier innerHTML plutôt que createTextNode(). Dans le cas décrit plus haut, c'est à dire l'insertion d'un texte dans un paragraphe vide, j'aurai utilisé sans complexe innerHTML.

Il faut néanmoins rappeler que l'insertion d'options (balise option) dans un select ou la création de cellules (balises td, tr) dans une table fait appel à d'autres fonctions
Auteur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/06/2007, 17h33   #10
Inactif
 
Avatar de Hibou57
 
Inscription : mars 2006
Messages : 852
Détails du profil
Informations forums :
Inscription : mars 2006
Messages : 852
Points : 398
Points : 398
Citation:
Envoyé par Auteur
[*]par contre, je dois l'avouer , si je dois insérer un texte non formaté dans une balise vide (p, div, span, td), j'utilise volontier innerHTML plutôt que createTextNode(). Dans le cas décrit plus haut, c'est à dire l'insertion d'un texte dans un paragraphe vide, j'aurai utilisé sans complexe innerHTML.
Oui, c'est vrai, et c'est la façon d'aborder la question qui peut faire toute la différence.

Si on prend innerHTML comme un moyen d'ajouter des neouds à un élément, alors on se trompe, car appendChild est plus efficace, car il est au niveau implémentation, directement en relation avec le représentation interne du navigateur

Mais si on veut ajouter un contenu préformaté dans un élément, alors innerHTML est tout à fait justifié, car il est fait pour ça. Exemple : quand on veut introduire du code HTML donné dans une boite de saisie par l'utilisateur/rice, ou encore quand on utilise une fonction renvoyant un texte formaté, plutôt qu'une simple chaîne de caractère (par exemple, une fonction renvoie une chaîne avec certains mots mis en gras... mais la fonction pourrait aprés tout également renvoyer un tableau de noeuds... ce n'est pas interdit)

La question à sa poser est « que veut-on faire ? »

Selon que la réponse sera « ajouter un noeud » ou « ajouter du texte préformaté », alors on choisira la première ou la deuxième solution.

Il y a un exemple que j'aimerais souligner, où l'usage de innerHTML est incontournable :

Pour bien présenter cet exemple, je vous laisse d'abord penser aux propriétés en écriture, du genre className ou setAttribut (name, value). Il n'existe pas de fonction setTagName, et tagName n'est pas en écriture. Pourtant il arrive que cela soit utile (si le nom de l'élément pouvait être assimilé à un attribut spécial, ce serait bien pratique). Dans ce cas, il n'y a pas d'autre choix que de créer un doublon, en créant un noeud avec createElement(tagName), copier les attributs (ce qui pose un léger problème avec IE, voir plus loin), en les scanant un par un, et ensuite, copier le contenu avec innerHTML (c'est évident dans ce cas là, que scaner les noeuds un par un serait innefficace et pénible, et il est préférable de se reporter à la fonction interne du navigateur, surement plus efficace pour les gros fragments tout entiers).

La petite note au sujet de IE : les attributs renvoyés par IE inlus les attributs infferés par défaut (comme l'attribut de langue). Ca peut être embétant, parce que le nombre d'attributs qui se trouvent alors dans la copie du noeud, peut être parfois nettement plus important que le nombre d'attributs contenu dans le code (le nombre sera d'autant plus important que le noeud aura un ou des parents qui auront définis des attributs héritables... la copie des attributs ne reflète alors plus du tout la réalité du code).

Je m'explique : si vous avez dans le source, un noeud <p id="truc>, et que vous voulez changez P en DIV, alors vous créer l'élément DIV, copier le innerHTML de P vers celui de DIV ; mais au moment de copier les attributs, vous devrez lire ceux de P, et là, Internet Explorer ne vous renverra pas seulement l'attribut id, mais également tout un tas d'autres attributs... ce n'est pas trés propre à mon avis... mais bon, ça n'empêche pas l'application de fonctionner non-plus (n.b. ce n'est pas un commentaire pour dire que IE n'est pas bien, parce que j'aime autant IE que les autres.. c'est juste une note comme les autres).
Hibou57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 03h07.


 
 
 
 
Partenaires

Hébergement Web