Normally when a page round trips to the server (or PostBack happens), the scroll position of the page resets and the user has to scroll back to the part where he/she was doing something. One of the nice little features in ASP.NET 2 is a page property called 'MaintainScrollPositionOnPostback' which as its name suggests, takes care of it in a way that just can't get any easier!
But the problem here is that, there may be other scroll bars in page (such as MultiLine TextBoxes, ListBoxes, ...) which there's no simple way to maintain their positions on postbacks. This situation gets even worse as we place UpdatePanels in the page and while there's [or seems to be] no postbacks, still scroll bars reset to zero on each request. As I couldn't find any SIMPLE solution for this, I tried to solve the problem myself and the result was a simple yet powerful script which I present it here.
There are two versions of the script available for download. Normal version (scrollsaver.js) is the main script which I attached just in case anyone wants to figure out how this all works and maybe fix its bugs and the minified version (scrollsaver.min.js) which is the one that you should actually use.
In order to use the script all you need is to add a reference to it anywhere in the page. The script takes care of everything else for you. Even if you have UpdatePanels, it'll detect them and still maintains scroll positions seamlessly. Just remember that only the scroll position of the elements which have their ID attribute set, can be maintained by this script!
Actually the idea isn't something new or unexpected at all! The Idea is just to simply store the scroll position of each element (along with window's scroll position) in a cookie before PostBack (or partial PostBack) and after the page comes back from the server, restore the scroll position of elements.
The biggest challenge is how to recognize elements after PostBack! The solution I used is to assume that all the elements have ID attribute. This assumption is not really far from reality, because normally when you place ASP.NET elements on the page, they have ID attribute and ASP.NET [somehow] manages to make this ID unique on client side which is great for our situation. The actual problem is when we place HTML tags like "div" directly in a page, which then we should double check them to have their ID attribute set. I suggest that besides ID attribute, add a runat="server" to the controls to ensure unique IDs on client side too.
The other [fairly simple] challenge is how to manage UpdatePanels which that's where add_beginRequest and add_endRequest comes in handy.
This solution is not server related so this script should simply work with any other platform (like JSP, PHP, ...) without any changes.
I've tested this script with major browser including IE(6+), FF(2+), Opera(9.6+), Chrome(1+) and Safari(3.2). Actually there's no [known to me] browser which this script can't handle!
The only problem in tests was with IE6 and Opera which both had problem handling scroll position of 'select' elements (that's ListBox in ASP.NET). The strange part is that even the latest release of Opera (Opera 10.0 Beta 3 - Build 1699) has this bug in it! Unfortunately I couldn't find any workarounds for this, so the script has problem handling scroll position of ListBoxs in IE6 and Opera!
I've attached two versions of this script (minified and normal) along with a demo project to this article.