Laisser la page au même niveau de défilement lors du PostBack avec ASP.NET

À chaque fois qu'un PostBack a lieu sur une page Web, le haut de la page est automatiquement réaffiché. Lorsque le contenu d'une page Web défile sur plusieurs écrans en hauteur, ceci nuit grandement à l'ergonomie. Imaginez : un internaute clique sur le bouton d'édition de la dernière ligne d'une longue liste de produits et sur le PostBack, il voit afficher les premiers produits du GridView. Pour pouvoir éditer les données, il doit faire défiler l'écran jusqu'à ce qu'il voit les boîtes d'édition du dernier produit.

▼Publicité

Pour contrer ce problème, il faut ajouter la directive MaintainScrollPositionOnPostback="true" dans la directive de page.

Ex :

Fichier .aspx (ASP.NET)

<%@ Page Language="C#" ... MaintainScrollPositionOnPostback="true" CodeFile="Produits.aspx.cs" Inherits="Produits" %>

Quand MaintainScrollPositionOnPostback ne fonctionne pas

Dans les conditions idéales, l'utilisation de MaintainScrollPositionOnPostback fonctionne à merveille. Mais si vous utilisez Chrome plutôt qu'IE, si vous utilisez un UpdatePanel, si vous utilisez du code JavaScript qui entre en conflit, si, si, si..., il peut arriver que la position de défilement de la page ne soit pas retenue sur le PostBack.

Bien que les causes peuvent être très diversifiées, l'ajout du script suivant dans la zone  <head> de la page semble régler le problème. 

Notez que lorsque ce script est présent sur la page, vous n'avez pas besoin d'ajouter le MaintainScrollPositionOnPostback dans la directive de page pour que la position de défilement soit conservée.

La logique que le script met en place est la suivante :

  • Lorsque la page est entièrement chargée en mémoire, elle vérifie si un élément de formulaire caché contient la valeur de défilement. Si oui, elle défile jusqu'à cette valeur.
  • À chaque fois que la page défile, on retient sa position de défilement. Si l'élément de formulaire prévu à cette fin n'existe pas, on le crée. On y stocke ensuite la valeur de défilement.
JavaScript

// pour régler le problème du MaintainScrollPositionOnPostback qui ne fonctionnait pas

// source : http://aspsnippets.com/Articles/ASPNet-MaintainScrollPositionOnPostback-not-working-in-Firefox-and-Chrome.aspx

window.onload = function () {

    var scrollY = parseInt('<%=Request.Form["scrollY"] %>');             

    if (!isNaN(scrollY)) {

        window.scrollTo(0, scrollY);

    }

};

window.onscroll = function () {

    var scrollY = document.body.scrollTop;

    if (scrollY == 0) {

        if (window.pageYOffset) {

            scrollY = window.pageYOffset;

        }

        else {

            scrollY = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0;

        }

    }

    if (scrollY > 0) {

        var input = document.getElementById("scrollY");

        if (input == null) {

            input = document.createElement("input");

            input.setAttribute("type", "hidden");

            input.setAttribute("id", "scrollY");

            input.setAttribute("name", "scrollY");

            document.forms[0].appendChild(input);

        }

        input.value = scrollY;

    }

};

Même code, version améliorée

Si plusieurs pages d'un site Web ont besoin de retenir le niveau de défilement, il devient intéressant de travailler avec des fonctions placées dans un fichier .js plutôt que de tout définir dans des fonctions anonymes.

Le code précédent peut donc être redéfini comme présenté plus bas. Seules les lignes du premier bloc de code devront être copiées sur les pages ciblées. Le gros du travail sera placé dans le fichier .js, tel que présenté dans le second extrait de code.

Remarquez que le window.onload du code original a été remplacé par l'appel jQuery $(function() {...}); Les deux formes sont semblables et fonctionnent bien pour le travail à réaliser ici. La différence entre les deux est que la version jQuery survient plus tôt dans le cycle de vie, soit dès que le DOM est entièrement chargé. Le window.onload ne sera exécuté que lorsque la page entière est chargée, incluant les images. 

La version jQuery a été utilisée ici par préférence personnelle plutôt que par nécessité.

Voici le code à copier sur chaque page qui a besoin d'être repositionnée après un PostBack :

Fichier .aspx (ASP.NET)

<script>

    // pour régler le problème du MaintainScrollPositionOnPostback qui ne fonctionnait pas

    // inspiré de : http://aspsnippets.com/Articles/ASPNet-MaintainScrollPositionOnPostback-not-working-in-Firefox-and-Chrome.aspx

    // adapté par Christiane Lagacé : http://christianelagace.com

    $(function() {

        atteindreDernierePositionDefilement(<%=Request.Form["scrollY"] %>);

    });

    window.onscroll = retenirPositionDefilement;

</script>

Attention : window.onscroll doit se voir assigner un gestionnaire d'événement. Il ne s'agit pas d'effectuer un appel à la fonction. C'est pourquoi il ne faut pas faire suivre le nom de la fonction par des parenthèses.

Et voici le code à écrire dans un fichier JavaScript, dont la référence sera également ajoutée sur les pages concernées :

JavaScript

// fait défiler la page jusqu'à l'endroit où elle était avant le postback

// inspiré de : http://aspsnippets.com/Articles/ASPNet-MaintainScrollPositionOnPostback-not-working-in-Firefox-and-Chrome.aspx

// adapté par Christiane Lagacé : http://christianelagace.com

function atteindreDernierePositionDefilement(position) {

    var scrollY = parseInt(position);

    if (!isNaN(scrollY)) {

        window.scrollTo(0, scrollY);

    }

}

// retient la position de défilement de la page

// inspiré de : http://aspsnippets.com/Articles/ASPNet-MaintainScrollPositionOnPostback-not-working-in-Firefox-and-Chrome.aspx

function retenirPositionDefilement() {

    var scrollY = document.body.scrollTop;

    if (scrollY == 0) {

        if (window.pageYOffset) {

            scrollY = window.pageYOffset;

        }

        else {

            scrollY = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0;

        }

    }

    if (scrollY > 0) {

        var input = document.getElementById("scrollY");

        if (input == null) {

            input = document.createElement("input");

            input.setAttribute("type", "hidden");

            input.setAttribute("id", "scrollY");

            input.setAttribute("name", "scrollY");

            document.forms[0].appendChild(input);

        }

        input.value = scrollY;

    }

}

Merci de partager ! Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInPin on PinterestShare on StumbleUponEmail this to someone
Catégories