Purplegoldfish Purplegoldfish - 5 months ago 37
Vb.net Question

Persist browser scroll position

I'm looking for a simple, efficient way to get the position of the browser vertical scrollbar and save it into a session variable in an ASP page.

What I'm trying to do is when the user changes a page I've the scroll position stored in a session variable so that when the user returns to the page the page will scroll to their last position.

Is there a way to do this? I've seen examples of persisting the scroll position on postback but nothing yet doing exactly what I'm trying to do :(

If anyone can point me in the right direction id be grateful.

EDIT:

Ok so based on the example below I noticed that when the user clicks a row in my gridview they navigate to the next page but my event handler never gets fired.
This leads me to suspect that the scroll position wasn't being saved, I'm guessing the form isn't being submitted)

My event handler looks like :

Protected Sub save(ByVal sender As Object, ByVal e As EventArgs) Handles ScrollPosition.ValueChanged
Session.Add("ScrollPosition", ScrollPosition.Value)
End Sub


I figured it was easiest to use the valueChanged event to grab the value and put it into the session

Next my Script.... I'm trying to do it based on my very limited knowledge of Jquery!

<script type="text/javascript">
$(function () {

//Retrieve and use the existing scroll position from the hidden field
var scrollPosition = $('#<%= ScrollPosition.ClientID %>').val();
$(window).scrollTop(scrollPosition);
/*
//Handle the main forms submit event and store the scroll position
$('#<%= form1.ClientID %>').submit(function () {
var currentScrollPosition = $(window).scrollTop();
$('#<%= ScrollPosition.ClientID %>').val(currentScrollPosition);
});
*/
});

$(document).ready(function () {
$("#gvTickets").click(function () {
var currentScrollPosition = $(window).scrollTop();
$('#<%= ScrollPosition.ClientID %>').val(currentScrollPosition);
})
});
</script>


The idea behind the script is that when a row in gvTickets is clicked the scroll position will be stored which should trigger my value changed event handler

I'm not getting any errors but neither am I getting the desired behaviour :(

Also in my page load I have :

If Not IsPostBack Then

If (Session("ScrollPosition") = Nothing) Then
ScrollPosition.Value = 0
Session("ScrollPosition") = 0
Else
ScrollPosition.Value = Session("ScrollPosition")
End If

Answer

Try storing the scroll position on submit of the form in a HiddenField control.

The HiddenField control will then be available in your code behind, so you can store the value as required.

You can then use the value from the HiddenField control to set the scroll position when the page loads.

See an example below (uses JQuery):

Markup

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <!-- Set the path to JQuery here -->
    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            //Add some line breaks
            for (i = 0; i < 1000; i++) {
                $('body').prepend('<br/>');
            }

            //Retrieve and use the existing scroll position from the hidden field
            var scrollPosition = $('#<%= ScrollPosition.ClientID %>').val();
            $(window).scrollTop(scrollPosition);

            //Handle the main forms submit event and store the scroll position
            $('#<%= form1.ClientID %>').submit(function () {
                var currentScrollPosition = $(window).scrollTop();
                $('#<%= ScrollPosition.ClientID %>').val(currentScrollPosition);
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <div style="position:fixed;top:0px;left:0px;">
                <asp:HiddenField ID="ScrollPosition" runat="server" Value="0" />
                <asp:Button ID="Button1" runat="server" Text="Post Back" OnClick="Button1_Click" />
                <asp:Label ID="CurrentScrollPosition" runat="server"></asp:Label>        
            </div>
        </div>
    </form>
</body>
</html>

Code Behind

protected void Button1_Click(object sender, EventArgs e)
{
    CurrentScrollPosition.Text = string.Format("Scroll position: {0}", ScrollPosition.Value);
}

Edit (Based on comments)

Try handling the window scroll event, updating the hidden field whenever the scroll position changes:

<script type="text/javascript">
    $(function () {

        $(window).scroll(function () {
            var currentScrollPosition = $(window).scrollTop();
            $('#<%= ScrollPosition.ClientID %>').val(currentScrollPosition);
        });

    });
</script>

Edit

For me, the following code sets the scroll position hidden field to 0 on load. Then on subsequent post backs stores the value in the hidden field in the "ScrollPosition" session variable.

I am then able to print the scroll position out to the screen. See below:

The control firing the postback in my example is a Button, however any control could initiate the postback and it will still function in the same manner.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        //Default to 0
        ScrollPosition.Value = "0";

        //If ScrollPosition session variable is null, store the default
        //Else set the scroll position to the value stored in session.
        if (Session["ScrollPosition"] == null)
        {
            Session.Add("ScrollPosition", ScrollPosition.Value);
        }
        else
        {
            ScrollPosition.Value = Session["ScrollPosition"].ToString();
        }
    }
    else
    {
        //On subsequent postbacks store the new scroll position
        Session.Add("ScrollPosition", ScrollPosition.Value);
    }

    OutputScrollPosition();
}

private void OutputScrollPosition()
{
    CurrentScrollPosition.Text = string.Format("Scroll position: {0}", Session["ScrollPosition"]);
}

Hope this helps.

Comments