Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Script de détection client-side du contexte de navigation

6 réponses
Avatar
Patrick 'Zener' Brunet
Bonjour.

J'ai pratiquement résolu le problème, mais à cause d'un petit détail de la
norme, j'ai dû resaloper un peu la solution, et bien sûr ça ne me satisfait
pas tout à fait du tout.

Le but:
Il s'agit de détecter un certain nombre de paramètres du navigateur en une
seule fois lors de son entrée sur le site, et de les passer au serveur pour
qu'il puisse en tenir compte dans la génération des pages. Ces paramètres
sont:
- la disponibilité et l'activation du Javascript,
- la disponibilité des cookies,
- la disponibilité du DHTML (en fait du innerHTML),
- la résolution de l'écran (largeur).

La justification de ce type de besoin est ici hors-sujet.

Ces détections peuvent se faire facilement (et uniquement a priori) avec du
Javascript, sachant que:
- pas de JS => pas de DHTML,
- pas de JS => wScreen = 0 = inconnue => média en résolution par défaut
- on peut détecter les cookies sans JS, mais comme un rechargement est
nécessaire, on profite de celui qui fait la détection du JS.

L'objectif:
Idéalement, on va charger une page de détection qui va ensuite provoquer une
indirection vers une autre page (script PHP), soit choisie parmi plusieurs,
soit avec des arguments d'URL traduisant les paramètres détectés.
Ceci doit se faire une fois à l'entrée sur le site, **PAS** au chargement de
chaque page !

Solution actuelle:
Je passe sur les détections d'attributs en Javascript, c'est banal.
Le point essentiel est la détection de l'activation de Javascript lui-même.
L'idée de base est de prévoir deux manières de faire la redirection.

Première version (simplifiée) de la page script:

<html>
<head>
<script type="text/javascript">
</script>
<noscript>
<meta http-equiv="refresh" content="0; URL=entry.php?js=no" />
</noscript>
</head>

<body>
<script type="text/javascript">
// <![CDATA[
function Entry()
{
window.top.location = "entry.php?js=yes";
return( false);
}
window.onload = Entry;
// ]]>
</script>
<noscript>
</noscript>
</body>
</html>

Ca marche correctement, avec ou sans Javascript, sur IE, Firefox et cie,
mais ça ne passe pas la validation W3C, parce que <noscript> est interdit
dans la section HEAD.
Effectivement, on l'utilise normalement dans BODY pour afficher un message
du genre: "Vous pas branché Javascript, allez mieux fair'fout...",
...ou alors pour inclure un contenu alternatif complet, ceci pour chaque
page (beuââârk !).

Evidemment si Javascript est fonctionnel, il faut que la redirection par le
<meta> ne soit pas exécutée, sinon on va servir deux pages ! A moins de
mettre un délai dans le <meta> et de demander au serveur de refuser la
seconde (double-beuââârk !)
Je ne veux pas non plus mettre dans le <noscript> du BODY un lien pour faire
manuellement la redirection en remplacement du <meta>.

J'ai donc tenté une autre méthode, consistant à utiliser Javascript
lorsqu'il est fonctionnel, pour générer dynamiquement un contenu capable de
neutraliser le <meta>:

<html>
<head>
<script type="text/javascript">
// <![CDATA[
document.writeln( '</scr' + 'ipt>' + '<' + '!' + '--'); /* See just
below */
// ]]>
</script>
<meta http-equiv="refresh" content="0; URL=entry.php?js=no" />
<!-- the JavaScript above comments the [meta] if enabled -->
</head>

<body>
<script type="text/javascript">
// <![CDATA[
function Entry()
{
window.top.location = "entry.php?js=yes";
return( false);
}
window.onload = Entry;
// ]]>
</script>
<noscript>
</noscript>
</body>
</html>

Et bien cette solution qui est en service sur mon site www.ipzb.fr semble
fonctionner très bien avec IE, Firefox et Opera, avec ou sans Javascript.
Cependant elle a un effet de bord bizarre: on voit s'afficher une paire de
tirets selon le navigateur, et donc je me pose des questions sur sa
robustesse avec des navigateurs exotiques...

Y aurait-il un expert très au courant de l'implémentation générale du
Javascript, et notamment de ce fonctionnement en génération dynamique par
document.write(), qui puisse m'éclairer sur les risques d'une telle
modification à la volée de la structure du code:

<script type="text/javascript">
// <![CDATA[
instruction; /* JS comment */
// ]]>
</script>
<meta />
<!-- HTML comment -->

devenant à la volée:

<script type="text/javascript">
// <![CDATA[
</script><!-- HTML comment ; /* JS comment */
// ]]>
</script>
<meta />
<!-- end of HTML comment -->

Et bien sûr si vous avez une meilleure solution pour éviter une telle
bidouille hideuse, ça m'intéresse...

C'est quand qu'un standard permettra enfin aux navigateurs de fournir
naturellement leurs "device capabilities" comme partout, même si ces infos
restent anonymes ?

Merci,
Cordialement,

--
/***************************************\
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
\***************************************/

6 réponses

Avatar
ASM
Patrick 'Zener' Brunet a écrit :
Bonjour.

J'ai pratiquement résolu le problème, mais à cause d'un petit détail de la
norme, j'ai dû resaloper un peu la solution, et bien sûr ça ne me satisfait
pas tout à fait du tout.



Je n'ai pas trop regardé ton détail qui complique bien les choses pour
qque chose de simple :
ordinairement on balance une page d'accueil en html normal
qui fera pour la partie du site sans JS

et en tout début de head on a un JS script qui fait ta 'tit' cuisine
cookies etc pour rediriger tt de suite sur la page d'accueil qui va bien
et avant chargement de la bête page html.

il n'y a pas à mettre du noscript
puisque sans JS on est déjà à bon port ...




--
Stephane Moriaux et son [moins] vieux Mac
Avatar
ASM
Patrick 'Zener' Brunet a écrit :

C'est quand qu'un standard permettra enfin aux navigateurs de fournir
naturellement leurs "device capabilities" comme partout, même si ces infos
restent anonymes ?



il te le fournit en ne répondant pas à la question

Donc toujours partir du principe qu'on a à faire à un sourd.
S'il entend il saura qu'il peut aller là où on pourra lui jouer la zick
qui va bien.


--
Stephane Moriaux et son [moins] vieux Mac
Avatar
ASM
Patrick 'Zener' Brunet a écrit :

Evidemment si Javascript est fonctionnel, il faut que la redirection par le
<meta> ne soit pas exécutée, sinon on va servir deux pages ! A moins de
mettre un délai dans le <meta> et de demander au serveur de refuser la
seconde (double-beuââârk !)



si le meta est apres le JS de redirection il est très probable qu'il ne
sera pas lu
donc il n'y aurait pas de beurk, ni simple ni multilpe, à prévoir

<html>
<head>
<script type="text/javascript">
self.location = 'entry.php?js=yes';
</script>
<title>Accueil temporaire</title>
<meta http-equiv="refresh" content="0; URL=entry.php?js=no" />
</head><body>
<h1>Accueil</h1>
<h3>Désolé l'adresse de cette page a changé</h3>
<p>Normalement vous auriez dê être redirigé vers la nouvelle page.<br />
si ce n'est fait merci de cliquer :
<a href="entry.php?js=no" onclick="location='entry.php?js=yes'; return
false;"> ici </a>
</body></html>



--
Stephane Moriaux et son [moins] vieux Mac
Avatar
Patrick 'Zener' Brunet
Bonjour.

Je réponds à ASM
qui dans 443ab850$0$18346$ a écrit :
Patrick 'Zener' Brunet a écrit :
Bonjour.

J'ai pratiquement résolu le problème, mais à cause d'un petit détail
de la norme, j'ai dû resaloper un peu la solution, et bien sûr ça ne
me satisfait pas tout à fait du tout.



Je n'ai pas trop regardé ton détail qui complique bien les choses pour
qque chose de simple :
ordinairement on balance une page d'accueil en html normal
qui fera pour la partie du site sans JS

et en tout début de head on a un JS script qui fait ta 'tit' cuisine
cookies etc pour rediriger tt de suite sur la page d'accueil qui va
bien et avant chargement de la bête page html.




Cela implique donc de charger une page "mode noscript" qui va
automatiquement se recharger si JS est activé.

Dans le principe ça m'ennuie si cette page n'est pas ultra-légère, assez
pour que son téléchargemnt soit plus ou moins instantané.

Donc ça on peut l'imaginer pour une telle page de détection, transformée en
page d'accueil très sommaire, mais ça suppose aussi qu'on va toujours entrer
par cette page.

Or dans mon architecture, rien n'empêche l'utilisateur (ou Google) de créer
un lien sur une page quelconque, et donc on entrera généralement par une
page interne.

Ce qui implique de monter ce système de rechargement en entête de chaque
page.

Techniquement je peux le faire par un composant incorporé par le serveur,
mais ce qui me gêne c'est que si la page a un minimum de contenu, le double
chargement devient très désagréable. Justement je viens de supprimer le
doublon au niveau du script de détection actuel.

J'ai également un petit doute (ta solution de la 3ème réponse) sur le fait
que le rechargement par JS arrive **toujours sur tout navigateur** à
court-circuiter la redirection par <meta> qui se trouve juste en dessous
dans le HEAD... Il y a là une concurrence entre deux threads (celui qui
charge la page et la machine JS), et le premier est actif à ce moment. J'ai
justement signalé un affichage bizarre qui appuie ce doute.

Donc comme l'absence de JS engendre un non-événement, et que je ne peux pas
compter sur sa détection par time-out, j'attends d'autres précisions
éventuelles sur ces particularités d'implémentation de JS pour tenter de
faire mieux que la solution actuelle...

Une autre solution que j'ai envisagée serait d'utiliser JS pour faire une
requête HTTP depuis la page (création dynamique d'une image par exemple),
sans pour autant la recharger, afin de passer une info au serveur. Mais il
reste alors à la sauvegarder côté serveur pour l'injecter dans les
paramètres d'URL au prochain changement de page, ce qui n'est pas forcément
évident...

A moins de redéfinir le mécanisme pour maintenir ces données dans les
paramètres de session et plus dans l'URL, c'est encore une lourde
transformation, mais c'est envisageable.

En fait j'ai déjà vu plusieurs discussions sur ce problème sur divers forums
de développement Web, et tout le monde semble s'y être cassé les dents.

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/
Avatar
ASM
Patrick 'Zener' Brunet a écrit :

Cela implique donc de charger une page "mode noscript" qui va
automatiquement se recharger si JS est activé.



non, qui va automatiquement aller chercher la bonne page à charger.
(ça ne se fait pas sur le 'onload' mais en direct, instantanément)

Dans le principe ça m'ennuie si cette page n'est pas ultra-légère, assez
pour que son téléchargemnt soit plus ou moins instantané.



Meuh non !
elle peut faire 10 km ça n'a pas d'importance.

si le JS est actif, dès qu'il interprète (dès qu'il lit)
location = 'truc.htm'
il court te chercher truc et le chargement en cours est interrompu.

Tu n'as pas essayé mon bout de code ?

Moi si et il est OK (IE, Safari, FF, Opera)
comme je m'en doutais.
http://perso.wanadoo.fr/stephane.moriaux/truc/recharge_entry.htm
à essayer avec et sans JS

et la même sans meta-refresh
http://perso.wanadoo.fr/stephane.moriaux/truc/recharge_entry_b.htm

Donc ça on peut l'imaginer pour une telle page de détection, transformée en
page d'accueil très sommaire,



Non, idéalement c'est la vraie page html sans JS qui est chargée par
défaut, et si JS, alors et seulement alors, on est redirigé dès avant
complet chargement vers la seurette munie de JS.

Or dans mon architecture, rien n'empêche l'utilisateur (ou Google) de créer
un lien sur une page quelconque, et donc on entrera généralement par une
page interne.

Ce qui implique de monter ce système de rechargement en entête de chaque
page.



tu n'avais pas parlé de la page d'accueil ?
tu veux généraliser la chose ?
alors ... faut c'qui faut ... non?

Techniquement je peux le faire par un composant incorporé par le serveur,
mais ce qui me gêne c'est que si la page a un minimum de contenu, le double
chargement devient très désagréable.



il n'y a pas de *double* chargement.

essaie avec le bout de code que j'ai donné et une page d'entrée bien
chargée (et bien sûr une autre nommée entry.php) sans le meta-refresh
puis avec le meta-refresh.

et si ça veut tt de même rafraichir par la méthode meta ce n'est pas
grave, il n'y a qu'à ne pas rafraichir puisqu'on est sur la bonne page
(celle sans JS)

En fait j'ai déjà vu plusieurs discussions sur ce problème sur divers forums
de développement Web, et tout le monde semble s'y être cassé les dents.



Le JS doit toujours être considéré *que* comme une béquille,
une page html doit *toujours* pouvoir *bien* fonctionner même si le JS
est désactivé.

(le menu coulissant !)


J'enfonce le clou,
le truc est tellement bête qu'on a du mal à se l'approprier :

- la page servie par défaut est celle html via php si besoin
- il n'y a pas besoin de recharger ou re-router vers une page
html sans JS puisqu'on y est déjà.
- elle comporte 1 ligne et une seule de JS (tout au début)
pour re-router vers la page avec JS avant son complet chargement.
- normalement la page avec JS doit pouvoir fonctionner sans.


Donc si on fait "normalement" on a une seule page munie de JS dont seuls
les navigateurs au JS actif sauront profiter du script.
Si le script JS est en fichier externe, les navigateurs sans JS (sauf IE
qui est trop bête) n'iront pas charger le script.

--
Stephane Moriaux et son [moins] vieux Mac
Avatar
Patrick 'Zener' Brunet
Bonjour.

Je réponds à ASM
qui dans 443ae4f0$0$21303$ a écrit :
Patrick 'Zener' Brunet a écrit :

Cela implique donc de charger une page "mode noscript" qui va
automatiquement se recharger si JS est activé.



non, qui va automatiquement aller chercher la bonne page à charger.
(ça ne se fait pas sur le 'onload' mais en direct, instantanément)




Oui, j'ai placé ça au onload parce que le code fait d'autres choses avant,
qui ont forcément lieu dans la section BODY (test du innerHTML notamment).

Dans le principe ça m'ennuie si cette page n'est pas ultra-légère,
assez pour que son téléchargemnt soit plus ou moins instantané.



Meuh non !
elle peut faire 10 km ça n'a pas d'importance.

si le JS est actif, dès qu'il interprète (dès qu'il lit)
location = 'truc.htm'
il court te chercher truc et le chargement en cours est interrompu.

Tu n'as pas essayé mon bout de code ?

[...]



Par choix professionnel, j'essaie de préférer la preuve formelle au constat
par essai, même si c'est pas toujours possible, surtout avec certaines NTIC
alakon :-(

Mais donc puisque tu as validé le système sur les "principaux" navigateurs,
et puisque effectivement dans cette configuration, on peut éviter le double
reload, je vais voir comment intégrer ça proprement dans ma mécanique (avec
les autres détections).

Donc avec un composant insérable en PHP dans chaque page, mais inséré
seulement dans la première chargée pour la session.

Ca va prendre un petit moment bien sûr...

Merci pour ce conseil,
Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/