ASP.NET Portable SmartNavigation

In ASP.NET 1.X I wanted to be able to use SmartNavigation for an application that had to support non-IE browsers. We also had a bunch of problems with bugs in IE IFRAMES that SmartNavigation managed to tweak, which inevitably pissed off our users.

I have not tried this code in ASP.NET 2.0, one would likely have to examine the postback Javascript and make some modifications here.

The basic idea to save the (X, Y) position of the page and on postbacks have the browser scroll to the previous (X, Y) position. The following code should be included in the System.Web.Controls.Page class for you application. You'll also have to modify the "myform" below to either have the same name as your <form> or even better write some additional code in the Page class to find the form an supply it's name.

UPDATE: I've updated this to support ASP.NET 2; however, I would rely on the updated navigation stuff in ASP.NET 2 and *not* use this.

private bool m_enableTrackPostBack = true;
public bool EnableTrackPostBack
{
get { return enableTrackPostBack; }
set { m_enableTrackPostBack = value; }
}

protected override void OnPreRender(EventArgs e)
{
if (EnableTrackPostBack)
{
RegisterHiddenField(VerticalPositionFieldName, String.Empty);
RegisterHiddenField(HorizontalPositionFieldName, String.Empty);
base.RegisterClientScriptBlock("MySubmit", GetDoPostBackHijackScript());
if (this.IsPostBack)
{
base.RegisterStartupScript("ScrollTo", GetLoadPositionScript());
}
}
base.OnPreRender(e);
}

private const string SaveScriptName = "TrackPostBackScrollPositionSave";
private const string LoadScriptName = "TrackPostBackScrollPositionLoad";
private const string VerticalPositionFieldName = "NAVVSPOS";
private const string HorizontalPositionFieldName = "NAVHSPOS";
private const string ScriptHiddenField = "document.forms[0].{0}.value";
private const string ScriptGetPositionLine = ScriptHiddenField
+ " = (navigator.appName == 'Netscape')
? window.page{1}Offset : document.body.scroll{2};";

private string GetLoadPositionScript()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<script language=\"JavaScript\">\n<!--\n");
sb.Append("function RestoreScrollPosition() { \n");
string x = (Page.Request[HorizontalPositionFieldName] == null ? "0"
: Page.Request[HorizontalPositionFieldName]);
if (x.Length == 0)
{
x = "0";
}
string y = (Page.Request[VerticalPositionFieldName] == null ? "0"
: Page.Request[VerticalPositionFieldName]);
if (y.Length == 0)
{
y = "0";
}
sb.AppendFormat("\tscrollTo({0},{1}); \n", x, y);
sb.Append("}\nRestoreScrollPosition(); \n// -->\n");
sb.Append("</script>");

return sb.ToString();
}

private string GetDoPostBackHijackScript()
{
return @"
<script language=""javascript"">
<!--
function MyOnSubmit()
{
var thetop;
var theleft;
var theform;
if (window.navigator.appName.toLowerCase().indexOf(""netscape"") > -1) {
thetop = window.pageYOffset;
theleft = window.pageXOffset;
}
else {
if (document.documentElement && document.documentElement.scrollTop) {
thetop = document.documentElement.scrollTop;
theleft = document.documentElement.scrollLeft;
} else if (document.body) {
thetop = document.body.scrollTop;
theleft = document.body.scrollLeft;
}
}
document.forms[0].NAVVSPOS.value = thetop;
document.forms[0].NAVHSPOS.value = theleft;
return true;
}

function MyDoPostBack(eventTarget, eventArgument)
{
if (window.navigator.appName.toLowerCase().indexOf(""netscape"") > -1) {
theform = document.forms[""myform""];
}
else {
theform = document.myform;
}
if (theform.onsubmit == null || theform.onsubmit()) {
return __oldPostBack(eventTarget, eventArgument);
}
}
var __oldPostBack = __doPostBack;
__doPostBack = MyDoPostBack;
// -->
</script>";
}

About this entry