Javascript dégradable, <yesscript> ?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

17 févr. 2008, 22:10

Oh, hai.

On sait qu'il est de bon ton de faire du Javascript dégradable, c'est-à-dire qui interfère le moins possible avec le bon déroulement d'une page, qu'il soit activé ou non. On connait la balise <noscript> qui permet d'afficher du contenu uniquement aux utilisateurs ayant désactivé Javascript. Mais comment afficher du contenu uniquement aux utilisateurs l'ayant activé ?

À l'heure actuelle, mon cœur penche vers ceci, à place entre les balises <head> de votre document :

Code : Tout sélectionner

<style type="text/css" id="degradable_js_stylesheet"> .js_required { display: none; } </style> <script type="text/javascript"> var stylesheet = document.getElementById('degradable_js_stylesheet'); stylesheet.parentNode.removeChild(stylesheet); </script>
Le principe étant de d'ajouter la classe "js_required" à tous les éléments à cacher si Javascript est désactivé, de tous les cacher par CSS et annuler cet ordre par Javascript le plus tôt possible pour éviter d'avoir un effet de clignotement au moment du chargement de la page.

Pendant un moment j'avais pensé mettre le <style> entre des balises <noscript> mais ce n'est pas permis par HTML. Est-ce que quelqu'un aurait devisé une méthode plus pratique ou performante ? Je suis tout ouïe, merci :)

ViPHP
ViPHP | 5924 Messages

17 févr. 2008, 22:37

Un document.write() ?

Mammouth du PHP | 2937 Messages

17 févr. 2008, 22:48

Pour ma part, je pencherais sur l'ajout d'une classe à chaque élément qu'on souhaite masquer en JavaScript. En JavaScript, il suffirait de boucler chaque élément et d'ajouter le style display: none chaque fois qu'on trouve le nom de la classe cherchée.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

18 févr. 2008, 00:04

Un document.write() ?
L'embêtant d'un document.write() (ou des appels d'appendChild, innerHTML, etc...) c'est que c'est relativement lent et ça force à mélanger HTML et Javascript. Ça interfère également avec le processus de validation du document.
Pour ma part, je pencherais sur l'ajout d'une classe à chaque élément qu'on souhaite masquer en JavaScript. En JavaScript, il suffirait de boucler chaque élément et d'ajouter le style display: none chaque fois qu'on trouve le nom de la classe cherchée.
Le principe est de faire apparaître les éléments nécessitant Javascript, et dans ce cas il faudrait faire un "display:block" ou plutôt retirer la valeur de l'attribut "display" pour lui faire adopter sa valeur par défaut et ne pas interférer avec les éléments inline. Malheureusement, ça voudrait dire qu'il faut faire une boucle sur tous les éléments de la page, donc ça peut prendre un petit peu de temps. De plus, cette boucle ne pourrait être exécutée qu'une fois le DOM complètement chargé et probablement déjà au moins partiellement affiché. C'est pourquoi j'ai opté pour un script que l'on peut placer le plus haut possible dans le document, de façon à minimiser le nombre de repaint/reflow.

Je ne l'ai pas précisé, mais j'ai aussi essayé de modifier le CSS via l'interface DOM, mais c'est plus long à taper et comme toujours la gymnastique pour le faire fonctionner sous IE est très désagréable.

Pour l'heure, retirer ce stylesheet spécial par removeChild() semble est la solution la plus rapide et la plus simple, mais si vous avez d'autres idées n'hésitez pas ! ;)

ViPHP
AB
ViPHP | 5818 Messages

18 févr. 2008, 02:12

Je prend note.

Jusqu'à présent je n'avais à gérer qu'un bloc ou deux donc je faisais :

Code : Tout sélectionner

<body onload="document.getElementById().style.display = 'block' ;">
après les avoir cachés par CSS

Pour plus d'un bloc ta solution me parait tip top :pouce:
Modifié en dernier par AB le 19 févr. 2008, 22:25, modifié 1 fois.

ViPHP
ViPHP | 4674 Messages

18 févr. 2008, 10:50

À propos de rapidité, tu devrais jeter un oeil sur l'intégration native de certaines fonctions Javascript comme getElementsByClassName pour WebKit. Apparemment, ce procédé devrait s'étendre à plusieurs navigateurs par la suite tellement les résultats sont autrement performants.

Edit : les commentaires sont également intéressants :).
Modifié en dernier par Hywan le 26 févr. 2008, 01:20, modifié 1 fois.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

ViPHP
AB
ViPHP | 5818 Messages

18 févr. 2008, 13:29

À propos de rapidité, tu devrais jeter un oeil sur l'intégration native de certaines fonctions Javascript comme getElementsByClassName pour WebKit. Apparemment, ce procédé devrait s'étendre à plusieurs navigateurs par la suite tellement les résultats autrement performants.
Edit : les commentaires sont également intéressants :).
On l'aura attendue longtemps cette fonction... Et le temps que les utilisateurs aient tous des navigateurs qui la supportent, les solutions comme celle d'Hubert ont encore de longues années devant elles :wink:

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

18 févr. 2008, 22:51

Je procède comme ça aussi, j'utilise ce genre de choses en général :

Javascript

Code : Tout sélectionner

Event.observe(window, "load", function(){ $A(document.getElementsByTagName("yesscript")).each(function(element){ element.show(); }); });
HTML

Code : Tout sélectionner

<span class="yesscript">Only si tu as enablé Javascript my buddy-friend :)</span>

ViPHP
ViPHP | 4674 Messages

19 févr. 2008, 11:06

À propos de rapidité, tu devrais jeter un oeil sur l'intégration native de certaines fonctions Javascript comme getElementsByClassName pour WebKit. Apparemment, ce procédé devrait s'étendre à plusieurs navigateurs par la suite tellement les résultats autrement performants.
Edit : les commentaires sont également intéressants :).
On l'aura attendue longtemps cette fonction... Et le temps que les utilisateurs aient tous des navigateurs qui la supportent, les solutions comme celle d'Hubert ont encore de longues années devant elles :wink:
Ça arrivera plus vite que tu ne le crois ;-). Si WebKit l'implémente, alors Safari et Konqueror l'auront. Firefox est séduit par ces résultats, peut-être pour la bêta 4 de ffx 3 ? Non j'en doute, mais pour Firefox v4, il y a de forte probabilité pour que ça arrive. Comptons alors 2 ans maximum.
Et pour IE ... euh c'est quoi déjà comme logiciel ça ?

On notera au passage que XPath est plus rapide que DOM. Comme Hubert s'intéressait à XML la dernière fois, tu peux sûrement savoir si XPath est activé côté client (navigateur), car les résultats sont sensiblement plus performants.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

19 févr. 2008, 11:16

À ma connaissance, à peu près tous les navigateurs proposent XPath. Le problème d'XPath étant qu'il est super-relou à utiliser en JS :( [edit: ah ben non, moins que dans mes souvenirs. En tout cas, dans les navigateurs récents]

Ceci dit, comme je le disais plus haut, les solutions à base de getElementsByTagName() ont le désavantage de nécessiter d'attendre que le DOM soit complétement chargé et peuvent potentiellement entrainer plusieurs reflow puisque chaque élément est modifié séparément, c'est pourquoi je m'oriente vers quelque chose qui puisse être placé dans le <head>. D'après ce que j'ai pu voir sur les navigateurs à ma disposition, ma solution actuelle pourrait être la meilleure, mais je reste vigilant et n'écarte pas la possibilité que l'on trouve un moyen plus pratique.

ViPHP
ViPHP | 4674 Messages

24 févr. 2008, 17:10

Si XPath est moins ch*ant à utiliser, et qu'il ne nécessite pas que le DOM soit chargé, ne serait-il pas préférable de le préférer à getElementsByTagName() ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

24 févr. 2008, 17:26

Comme pour getElementsByTagName(), tu dois attendre d'avoir chargé le DOM pour utiliser XPath. Tu peux utiliser l'un comme l'autre dans <head /> mais ça ne servirait à rien puisque le document n'a même pas de <body /> à ce moment là.

...d'où l'approche actuelle consistant à virer du document cet élément <style /> avant même d'avoir commencé à peindre la page.

ViPHP
AB
ViPHP | 5818 Messages

02 nov. 2008, 18:41

J'avais gardé cette astuce dans mes cartons ...

On peut également utiliser ce script (premier post donné par Hubert) pour cacher des éléments pour les seuls navigateurs ayant JS activé.
C'est très pratique quand on doit modifier des styles css sans attendre le chargement de la page, et sans avoir à modifier les styles Css via javascript (ce qui peut s'avérer pénible et délicat pour être compatible avec la majorité des navigateurs).

Code : Tout sélectionner

<style type="text/css"> .cachetext { visibility:hidden; } </style> <style type="text/css" id="degradable_js_stylesheet"> .affichetext { visibility:visible; } </style> <script type="text/javascript"> var stylesheet = document.getElementById('degradable_js_stylesheet'); stylesheet.parentNode.removeChild(stylesheet); </script> //... HTML <div class = "cachetext affichetext">Contenu</div>
Gros avantage : la simplicité et la compatibilité du code avec quasiment tous les navigateurs.

Le seul tout petit problème : cette syntaxe n'est pas valide XHTML 1.1 mais "seulement" XHTML 1.0 scrict.

ViPHP
ViPHP | 4674 Messages

02 nov. 2008, 22:11

Hey :),

On préférera utiliser display à visibility en revanche.
Et je ne comprends pas pourquoi ce n'est pas valide XHTML 1.1 ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

ViPHP
AB
ViPHP | 5818 Messages

02 nov. 2008, 22:29

Hey :),

On préférera utiliser display à visibility en revanche.
Et je ne comprends pas pourquoi ce n'est pas valide XHTML 1.1 ?
Taratata... on préférera utiliser ce que l'on veux suivant les circonstances. La propriété "visibility" ayant l'avantage de réserver les dimensions du bloc, ce qui peut être utile dans certains cas.

Concernant la non validation en XHTML 1.1, le validateur dit qu'il ne doit pas y avoir d'id dans une balise <style type="text/css"...
Maintenant si tu me demandes pourquoi ils ont décidé ça ... bah on va rentrer dans le conceptuel du comment du pourquoi. Et pour m'être penché à quelques reprises sur ce genre de décisions, je te laisse volontiers la suite :D
Modifié en dernier par AB le 02 nov. 2008, 22:42, modifié 1 fois.