FRAMES POUR MASTERS EN PHP
Gestion des favoris, de l'historique, organisation des fichiers et référencement
Cet article est la suite de Frames pour Phd en PHP dont la .lecture préalable n'est pas obligatoire pour aborder ce qui suit.
Rappel des conventions
CadreDef.php est le fichier de définition des cadres dont le résultat se présente à l'écran ainsi :
Inscription dans les favoris
Pour permettre l'ajout aux favoris d'une page framée avec Internet Explorer, voici le code HTML à placer dans la section <body> :
<a href="javascript:window.external.AddFavorite(document.URL,document.title);">IE : Ajouter cette page aux favoris</a>
Netscape gère l'inscription dans les signets des pages framées via le click droit de la souris. On peut néanmoins inclure un message d'aide qui apparait lorsque l'internaute clique sur le lien :
<Head>
...
<SCRIPT Language="javascript">
function favoris()
{
var isNS = (navigator.appName == "Netscape") ? 1 : 0;
if(isNS)
{
alert('Netscape : par le clic droit de la souris : Ce cadre >> ajouter un signet');
}
else
{
window.external.AddFavorite(document.URL,document.title);
}
}
</SCRIPT>
...
<Head>Le lien devient :
<a href="javascript:onclick=favoris()">Ajouter cette page aux favoris</a>
ou encore :
<a href="javascript:onclick=favoris()"><img src="MonChemin/MonBouton.gif width="25" height="20" alt="Ajouter aux favoris"></a>
Navigation dans l'historique arrière
La navigation dans l'historique oblige l'internaute au recours à de nombreux clics lorsque plusieurs pages ont été mouvementées simultannément, par exemple lorsqu'une page texte.php chargée en Cadre3 a automatiquement ouvert un menu en Cadre2. Une procédure javascript placée dans le fichier Texte.php qui transite en Cadre3 pourra lui simplifier la tâche :
Code à placer en section <Head> :
<SCRIPT Language="javascript">
<!-- Netscape, IE et Mozilla-->
function Retour()
{
window.history.go(-1);
setTimeout("Retour()",500);
}
</SCRIPT>Et le lien suivant doit être placé dans Texte.php en section <Body> pour permettre à l'internaute d'actionner le retour arrière :
<a href="javascript:onclick=Retour()">Retour</a>
Explications :
1) Le principe consiste à lancer autant de retours arrières que nécessaire. Lorsque la page qui contient et exécute la procédure n'est plus présente en mémoire, la procédure s'arrête. En d'autres termes, dès que Texte.php est remplacé, les variables chutent et la procédure s'interrompt.
2) Mais dans les faits, la procédure poursuivrait ses retours arrières dans l'historique pour ne jamais s'interrompre sans la temporisation introduite après chaque itération ! Le "SetTimeout" réglé sur 1/2 seconde laisse le temps au navigateur de prendre en compte le changement de page. Le délai peut baisser jusqu'à 75ms pour ne pas impatienter l'internaute quand 3 ou 4 pages sont à mouvementer.
3) La procédure ne fonctionnerait pas dans une boucle "for" ou "while", d'où l'obligation de répéter l'instruction "Retour()". De même, "window.history.back()" ne fonctionne pas avec Netscape. La syntaxe requise est donc précisément celle exposée.
4) Néanmoins, ce script ne fonctionne pas si on a utilisé l'instruction "replace" lors du chargement d'un fichier dans l'un ou l'autre cadre.
Historique arrière après une instruction "replace"
Rappel et illustration de la fonction replace :
<SCRIPT Language="javascript">
window.open("Menu.php","Cadre2","replace");
</SCRIPT>L'instruction "replace" efface l'enregistrement précédent de l'historique de Cadre2 et le remplace par Menu.php sans toutefois affecter les enregistrements précédents et ceux des autres cadres. Mais après une telle instruction, le navigateur s'emmèle les pédales et requiert d'être plus explicite. Deux possibilités :
1) Préciser le nom du cadre
<SCRIPT Language="javascript">
function Retour()
{
parent.Cadre2.history.go(-1);
parent.Cadre3.history.go(-1);
setTimeout("Retour()",250);
}
</SCRIPT>2) Indiquer la destination dans l'historique
La procédure php qui suit provient de l'article précédent où la variable $Texte contenait le nom du fichier chargé précédemment et inscrit dans la table Session :
<?
$SqlSelect = "Select NomDuFichier from Session where AdresseIP = '$AdresseIP'" ;
$result = mysql_query($SqlSelect) ;
$row = mysql_num_rows($result);
$Texte = mysql_result($result, '0', 'NomDuFichier');
?>(On aurait pu utiliser le referrer au lieu de la table Session : $Texte = $HTTP_REFERER;).
<head>
...
<SCRIPT Language="javascript">
function Retour()
{
var isNS = (navigator.appName == "Netscape") ? 1 : 0;
if(isNS)
{
parent.Cadre2.history.go(-1);
parent.Cadre3.history.go(-1);
}
else
{
history.go(<? echo "$Texte" ?>);
}
}
</SCRIPT>
...
<head>Noter que Netscape ne reconnait pas "history.go("NomDuFichier")", raison pour laquelle on maintient pour lui la procédure précédente. Noter aussi que IE ne saura pas refaire le chemin inverse dans l'historique "avant" après l'instruction "history.go("NomDuFichier")". La première solution est pour l'instant la plus satisfaisante, mais les correctifs seront donnés plus loin.
Navigation dans l'historique avant
La navigation dans l'historique avant fonctionne selon la même logique que l'arrière. Exemple:
<SCRIPT Language="javascript">
function Avant()
{
<!--Netscape, IE et Mozilla-->
window.history.go(+1);
setTimeout("Avant()",500);
}
</SCRIPT>et
<a href="javascript:onclick=Avant()">Avant</a>
Mais il n'y a aucune solution simple pour l'historique avant dans le cas où une instruction "replace" a été exécutée dans l'un des frames ou si on a eu recours à "history.go("NomDuFichier")" pour le retour arrière. Il faudra dans ces cas reconstruire partiellement la fonction historique.
Historique avant suite à l'instruction "replace"
Pour garder la trace des fichiers mouvementés dans Cadre3, on peut utiliser un iframe caché qui conserve leurs noms à chaque retour arrière et qui les recharge en mémoire lors du déplacement avant dans l'historique :
Pour déclarer l'iframe "CadreIF" dans Texte.php :
<body>
...
<iframe allowTransparency="true" frameborder="0" name="CadreIF" src="Fonction.php<? echo ""?".$_Get[ListeHisto]" ?>" height="1" width="1" scrolling="no"></iframe>
</body>Explications :
1) L'iframe CadreIF de dimension 1 x1 pixel est de plus transparent, donc invisible.
2) Il contient les fonctions Avant1() et Avant2() dans le fichier "Fonction.php".
3) La variable $ListeHisto liste les fichiers mouvementés lors des déplacements dans l'historique arrière.
Code dans Texte.php pour le déplacement avant :
<a href="javascript:onclick=window.CadreIF.Avant2()">Avant</a>
Explication :
CadreIF est le nom de l'iframe et Avant2() la fonction appelée dans CadreIF pour commander le déplacement "avant" dans l'historique.
Code de la fonction Retour() dans Texte.php en section <head> :
<SCRIPT Language="javascript">
function Retour()
{
window.CadreIF.Avant1();
parent.Cadre2.history.go(-1);
parent.Cadre3.history.go(-1);
}
</SCRIPT>Explication :
Avant1() est la fonction appelée dans CadreIF pour conserver la trace des fichiers mouvementés lors des déplacements dans l'historique arrière.
Code des fonctions Avant1() et Avant2() :
<?php
//* Insérer ici la procédure de connection à la base
AdresseIP = $REMOTE_ADDR;//* Obtenir le nom du dernier fichier mouvementé dans la table Session
$sqlselect = "Select NomDuFichier from Session where AdresseIP = '$AdresseIP'";
$resultat = mysql_query($sqlselect);
$FichierSuivant = mysql_result($resultat, '0', 'NomDuFichier');//*Organiser et enrichir la liste des fichiers
$FonctionPhp = strstr("?","FichierSuivant=".$FichierSuivant.$ListeHisto);
$ListeHisto = str_replace("?", $FonctionPhp);
$FonctionPhp = "Fonctions.php?".$ListeHisto;
?><SCRIPT Language="javascript">
function Avant1()
{
window.open("<? echo "$FonctionPhp" ?>","CadreIF");
}
function Avant2()
{
window.open("<? echo "$FichierSuivant" ?>","Cadre3");
}
</SCRIPT>Définition de la fonction Avant() dans Texte.php en section <body> :
<a href="javascript:onclick=window.CadreIF.Avant2()">Avant</a>
Explications :
La fonction avant1() :
1) Le principe consiste à conserver la trace des fichiers de l'historique arrière pour les rendre disponibles lors du déplacement en chemin inverse.2) Le clic "Arrière" lance la fonction avant1() de fonction.php dans CadreIF.
3) Fonction.php est rechargé tout en se transmettant dans son URL la liste des fichiers mouvementés de Cadre3. La liste est reformatée.
4) Le temps de chargement n'est pas pénalisé car fonction.php ne pèse que 5ko.
La fonction avant2() :
1) Le principe consiste à actualiser et réorganiser la liste des fichiers au fil des retours arrière dans l'historique. Le premier est effacé, le second devient premier, le troisième second ...etc.
2) Le clic "Avant" lance la fonction avant2() de Fonction.php dans l'iframe.
3) La fonction avant2() charge le dernier fichier mouvementé en Cadre3.
4) Le chargement s'effectue partiellement depuis la mémoire cache et les images et objets sont trouvés sur le disque local.
5) La commande window.open("<? echo "$FichierSuivant" ?>","Cadre3") recrée l'historique si bien que history.go("NomDuFichier") redevient opérationnel (IE et Mozilla).
Organisation des fichiers
Il faut désormais organiser le système de fichiers sur disque. La solution la plus simple et la moins coûteuse consiste à placer tous les fichiers Texte, Menus, SousMenus et de procédures dans un seul et même répertoire. Mais la clarté d'administration pour les grands sites en pâtit. Une alternative consiste à dédier un répertoire aux procédures communes. Elles peuvent être rappatriées dans Texte.php par une instruction php "include" :
<head>
<title>Mon Titre</title>
...
< ?php
//*Procédure de conection à la base;
include("Procedures/Proc.txt");
?>
...
</head>L'extension "txt" de 'Proc' garantit que le code php s'exécute dans le fichier appelant. Avec une extension php il s'exécuterait dans le répertoire source. Hors, Texte.php doit à un moment déterminer son propre nom ($_SERVER['PHP_SELF'] dans l'article précédent) si bien que la variable doit se calculer dans Texte.php. Le fichier Proc.txt démarre et se termine par les délimiteurs php <? et ?> comme suit :
< ?
//*Ici s'insèrent les procédures php communes aux fichiers qui transitent dans Cadre3 sous la forme exacte où elles ont été définies dans cet article et le précédent.
?>
A la suite s'insèrent les procédures javascript communes de la section head, ou sinon un lien vers un fichier "js" qui regroupe les procédures javascript :<script src="Cadre3.js"></script>
Au résultat, la publication d'un texte ne prend que quelques instants. Une fois mis au point son HTML, il ne reste qu'à y inclure ces trois lignes, les mêmes toujours au même endroit. Le système de navigation avec frames se transforme en une véritable machine à publier et dote l'administrateur d'une grande réactivité. Et avec les procédures ainsi centralisées il bénéficie, en cas de modifications à apporter à Proc.txt, de l'effet de levier sur le site tout entier.
Note sur la sécurité :
Il faut restreindre le CHMOD du répertoire dédié aux procédures php et le limiter à un accès local grâce au fichier .httacess dont le seul contenu sera :
deny from all
Sans quoi, n'importe qui pourra prendre connaissance du code php et des noms de variables pour pirater le site. La vulnérabilité du php provient de la possibilité de détourner les variables pour y injecter du code exécutable. Mais avec le système de fichiers "txt" et la protection du répertoire, le niveau de sécurité est acceptable. De plus, le fichier de définition des cadres, dont l'URL est la seule accessible par la barre d'adresse, joue le rôle d'un premier niveau de barrage.
Référencement des frames
Le référencement des sites tout en frames n'est pas compliqué. Il suffit de relier chacune des pages qui transite dans "Cadre3" par des liens. Le moteur d'indexation les suivra et le site tout entier sera indexé. Voyez l'extensivié du référencement par www.google.fr/ avec une simple recherche search?q=nostradamia&hl=fr&lr=lang_fr&filter=0 selon cette méthode et rien d'autre. Vous verrez aussi une liste de moteurs qui ont indexé le site.
En revanche, vous pouvez vous attendre à quelques discriminations dénuées de justification technique du fait de l'apriori et des préjugés d'employés et éditeurs des moteurs de recherche qui ne veulent pas admettre avoir eu tort d'un bout à l'autre du débat sur les frames, même 2 ans plus tard. Il n'y a aucune raison objective de réfuter les frames, et il n'y en a jamais eu. Mais le monde est truffé d'idiots et d'incompétents aussi bien dans le domaine du référencement qu'ailleurs. En fait, la plus grande difficulté pour référencer un site comme Nostradamia provient de sa taille de 1000 pages et de ses 6900 liens. Les grands moteurs y parviennent sans difficulté, mais l'hébergeur cale lorsqu'il s'agit de mettre à dispo un nombre de pages important en peu de temps, si bien que le robot doit s'y reprendre à plusieurs fois, s'il le veut bien. En tout état de cause, il n'y a aucun rapport avec les frames !
Certains robots peu performants s'arrêtent à la première instruction "<frameset>. Il faut donc interdire l'accès au fichier de définition des pages de cadres dans robots.txt. Et comme par ailleurs les robots n'exécutent pas le javascript, l'instruction de chargement des pages de cadres sera ignorée.
Le point de départ d'indexation du site, c'est à dire la page d'index principale "index.php" ou "index.htm", ne doit jamais définir un cadre (pas d'instruction <frameset>). En y plaçant un lien qui pointe vers le plan du site, l'indexation exhaustive est garantie à condition de limiter le nombre de liens par page à moins de 100, maximum pris en compte par Google.
La plupart des auteurs expliquent qu'il faut placer tous les liens du site entre les balises <noframe> et </noframe> du fichier de définition des cadres. C'est lourd et cela ne sert à rien. Et comme il n'y a dans notre architecture qu'un seul cadre pour tous les fichiers du site, cela alourdirait inutilement sa taille qui doit au contraire rester ultra-light. Cet espace ne doit servir qu'à passer un message à l'internaute pour qu'il rétablisse l'option "frames" de son browser (Opera, Netscape et Foxpro possèdent cette option). En conclusion, l'incompatibilité des frames et du référencement est un mythe.
.
Récapitulatif
Ce système de navigation avec frames règle les problèmes du raffraîchissement d'écran, y compris lors de la navigation dans l'historique, celui de la multiplication des fichiers sur disque, du nombre de clics arrières, de l'administration des fichiers, du placement dans les favoris et du référencement.
Le prochain article traitera de l'ajustement au plus fin de la taille des textes, formulaires, images et tableaux au sein des pages contenues dans des cadres dont les informations doivent à tout moment rester visibles (un menu, un formulaire de recherche, une information ...). Il faudra tenir compte de la résolution d'écran, de la taille de la fenêtre active et du modèle de navigateur.
Vos commentaires et questions sont maintenant les bienvenus, c'est gratuit.
GP.