ToutSurTout.biz
Le DHTML


Assurer la compatibilité

Nous allons dans cette page détailler le fonctionnement du Dynamic HTML du script : Un calque toujours visible.

Objectif du script
Ce script permet de positionner un calque en haut de page, toujours visible, quelles que soient les actions du visiteur sur l'ascenseur.
Ce script est très utile pour afficher un logo ou un menu accessible en permanence par les visiteurs, même si la hauteur de la page dépasse celle de l'écran.
Pour tester ce script, utilisez l'ascenceur vertical et observez le logo en bas de la page.

Principe de fonctionnement
Les navigateurs ne possèdent pas l'événement onScroll qui détecterait l'action du visiteur sur les ascenseurs et le défilement de la page.
On utilise donc une astuce de programmation : un timer est déclenché pour scruter à intervalle régulier la position de la page et pour déplacer ainsi le calque afin de le maintenir toujours visible.
Pour limiter les saccades dû au déplacement du calque, le calque est déplacé progressivement, par incrément, vers sa position normale.

Explication du script
Voici le code source du script :

<SCRIPT language="javascript">
// PARAMETRAGE DU SCRIPT
var tjs_delai=30;
var tjs_max=50;
var tjs_mode=1; // 0 - calque toujours en haut de page / 1 - calque en bas

// LE RESTE NE CHANGE PAS
var tjs_hauteur=0;
function PrintCalque(left,top,width,height,contenu) {
    tjs_hauteur=height;
    if ((document.all)||(document.getElementById)) {
        var Z="<DIV id='tomber' style='position:absolute;left:"+left+";top:"+top+";width:"+width+";height:"+height+"'>"+contenu+"</DIV>";
    } else {
        var Z="<LAYER name='tomber' left="+left+" top="+top+" width="+width+" height="+height+">"+contenu+"</LAYER>";
    }
    document.write(Z);
    setTimeout("Start()",tjs_delai);
}
function Start() {
    // Toujours en haut :
    //var delta=parseInt(document.getElementById("tomber").style.top-document.body.scrollTop);
    MoveLayer("tomber",GetTop("tomber"));
    setTimeout("Start()",tjs_delai);
}
function Debug() {
    var obj=document.body
    var Z="";
    for (var i in obj) {
        Z+=i+"="+obj[i]+"\n";
    }
    alert(Z);
}
function MoveLayer(nom,top) {
    if (document.getElementById) { //IE5 et NS6
        document.getElementById(nom).style.top=top;
    }
    if ((document.all)&&(!document.getElementById)) { //IE4 seul
        document.all[nom].style.top=top;
    }
    if (document.layers) { //NS4.X seul
        document.layers[nom].top=top;
    }
}
function GetTop(nom) {
    // Partie 1 : Récupération de la position du calque et de la page
    if (document.getElementById) { //IE5
        var pos=parseInt(document.getElementById(nom).style.top);
        var wintop=parseInt(document.body.scrollTop);
        var avail=document.body.clientHeight;
    }
    if ((document.getElementById)&&(!document.all)) { //NS6
        var pos=parseInt(document.getElementById(nom).style.top);
        var wintop=parseInt(window.pageYOffset);
        var avail=window.innerHeight;
    }
    if ((document.all)&&(!document.getElementById)) { //IE4 seul
        var pos=parseInt(document.all[nom].style.top);
        var wintop=parseInt(document.body.scrollTop);
        var avail=document.body.clientHeight;
    }
    if (document.layers) { //NS4.X seul
        var pos=parseInt(document.layers[nom].top);
        var wintop=parseInt(window.pageYOffset);
        var avail=window.innerHeight;
    }

    // Partie 2 : Traitement de la position
    if (tjs_mode==0) { // toujours en haut
        var delta=Math.ceil((pos-wintop)/3);
        if (delta>20) {delta=20;}
        if (delta<-20) {delta=-20;}
        var top=pos-delta;
    }
    if (tjs_mode==1) {// toujours en bas
        var delta=Math.ceil((pos-(wintop+avail-tjs_hauteur)));
        if (delta>tjs_max) {delta=tjs_max;}
        if (delta<-1*tjs_max) {delta=-1*tjs_max;}
        var top=pos-delta;
    }
    return top;
}

</SCRIPT>

Paramétrage du script
Le paramétrage du script se fait dans les premières lignes de code :
tjs_delai contient le délai du timer, soit le temps en millisecondes entre chaque vérification de la position du calque.
tjs_max contient le déplacement maximal en nombre de pixels du calque par intervalle de temps.
tjs_mode contient le mode d'affichage : 0 signifie que le calque sera toujours en haut et 1 toujours en bas.

Création du calque
Pour assurer la compatibilité entre tous les navigateurs, une fonction de création de calque a été définie PrintCalque(). Elle attend en paramètres la position et la taille du calque ainsi que la chaîne HTML qui sera affichée dans ce calque. Dans notre cas, il s'agit d'un logo du site.
Cette fonction affiche le code HTML correspondant sur la page selon le navigateur en cours et crée ainis un calque appelé tomber.
Le timer qui scrute la position du calque est lancé par setTimeout("Start()",tjs_delai); de la fonction PrintCalque().
Pour être sûr que le calque recouvre bien tous les éléments de la page, l'appel à PrintCalque(100,100,100,100,"TJS"); est placé à la fin de la page, juste avant la balise </BODY>.

Le timer
Le timer déclenche à intervalle régulier l'appel à la fonction Start() qui repositionne le calque à chaque passage. Le délai du timer est dans la variable tjs_delai, exprimé en millisecondes. Plus le délai est court, plus le calque sera replacé rapidement. En contrepartie, un délai court consomme du temps de traitement et peut ralentir un PC de petite puissance.
La fonction Start() contient 2 lignes :
MoveLayer("tomber",GetTop());
setTimeout("Start()",tjs_delai);
MoveLayer() est détaillée au prochain paragraphe. La 2ème ligne sert à maintenir le timer en fonctionnement.

Les fonctions de déplacement
La fonction MoveLayer() attend 2 paramètres, le nom du calque à déplacer et la position verticale.
Le nom du calque est tomber, la position du calque est calculée par la fonction GetTop() On utilise une fonction ici qui détecte le navigateur et qui gère la compatibilité entre navigateurs automatiquement. Ainsi, pour déplacer un calque, on ne se préoccupe pas de connaître le navigateur, on appelle juste MoveLayer().
Si le navigateur est IE5 ou NS6, on utilise la fonction getElementById() pour accéder au calque et lui affecter sa position verticale.
Si le navigateur est IE4, on utilise l'objet all.
Pour Netscape 4.X, on utilise l'objet layers.

La position du calque
La fonction GetTop() attend en paramètre le nom du calque à positionner.
Le corps de la fonction est découpée en 2 parties.
La première partie récupère, selon le navigateur, la position actuelle du calque dans la variable pos, la position de la page dans wintop et la hauteur utilisable de la page dans avail.
La deuxième partie réalise le calcul de la position en fonction du mode d'affichage.
Si tjs_mode vaut 0, le calque doit être toujours en haut. Sinon, le calque doit être en bas. La variable delta contient le nombre de pixels dont le calque doit se déplacer. Le maximum de déplacement est dans la variable tjs_max. Elle permet de limiter la vitesse de déplacement du calque et de le rendre ainsi plus lisse et moins saccadé.

Améliorations possibles
La première amélioration qui vient à l'esprit est d'ajouter la possibilité de faire coller le calque en horizontal, toujours sur un côté, à droite ou à gauche.
On peut aussi imaginer une gestion plus amusante du déplacement du calque, avec par exemple un rebond sur le bas de la page.