CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Sep 2004
    Posts
    65

    Save scroll position

    Hello all,

    I'm working on an intranet app targeting IE 6.0. I have a table nested in a scrollable div and I need to save the scroll position between postbacks, so I have a hidden field and 2 javascript functions. This works fine when the div is not nested in a table, but if the div in contained in a table, it doesn't work properly.

    Due to the framework I'm working in, I have to have the table surrounding my div, and I can't add anything to the body tag. The actual project is an ASP.NET 1.1 server control, so that is why I have the script tag that calls the gridLoad function after the div.

    This works:
    Code:
    <%@ Page Language="vb" AutoEventWireup="false" Codebehind="ScrollTest.aspx.vb" Inherits="AnotherTest.ScrollTest"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
      <HEAD>
        <title>ScrollTest</title>	
        <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
        <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
        <meta name=vs_defaultClientScript content="JavaScript">
        <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body >
      <script language="javascript">
      function saveScroll()
      {
    	var pos = document.getElementById('hdnScrollPos');
    	pos.value = event.srcElement.scrollTop;
      }
      function gridLoad(gridID, posID)
      {
    	var el = document.getElementById(gridID);
    	el.scrollTop = document.getElementById(posID).value;
      }
      </script>
    	
        <form id="Form1" method="post" runat="server">
    		<INPUT id="hdnScrollPos" type=hidden runat="server" NAME="hdnScrollPos">
    		<div id="divScroll" style="OVERFLOW:auto;WIDTH:70px;HEIGHT:100px" onscroll="saveScroll()">
    			<table>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    			</table>
    		</div>
    		<asp:Button id=Button1 runat="server" Text="PostBack"></asp:Button>
    		<script language="javascript">gridLoad('divScroll','hdnScrollPos');</script>
        </form>
    			
      </body>
    </HTML>
    But this doesn't work when it's in a table...
    Code:
    <%@ Page Language="vb" AutoEventWireup="false" Codebehind="ScrollTest.aspx.vb" Inherits="AnotherTest.ScrollTest"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
      <HEAD>
        <title>ScrollTest</title>	
        <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
        <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
        <meta name=vs_defaultClientScript content="JavaScript">
        <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body >
      <script language="javascript">
      function saveScroll()
      {
    	var pos = document.getElementById('hdnScrollPos');
    	pos.value = event.srcElement.scrollTop;
      }
      function gridLoad(gridID, posID)
      {
    	var el = document.getElementById(gridID);
    	el.scrollTop = document.getElementById(posID).value;
      }
      </script>
    	<table>
    		<tr>
    			<td>
        <form id="Form1" method="post" runat="server">
    		<INPUT id="hdnScrollPos" type=hidden runat="server" NAME="hdnScrollPos">
    		<div id="divScroll" style="OVERFLOW:auto;WIDTH:70px;HEIGHT:100px" onscroll="saveScroll()">
    			<table>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    			</table>
    		</div>
    		<asp:Button id=Button1 runat="server" Text="PostBack"></asp:Button>
    		<script language="javascript">gridLoad('divScroll','hdnScrollPos');</script>
        </form>
    			</td>
    		</tr>
    	</table>
      </body>
    </HTML>
    The code behind is the default provided by VS2003, the postback button does nothing but cause post back.

    Any ideas on why it doesn't work when it is wrapped up in a table? or any ways around it?

    Thanks,
    Ranthalion

  2. #2
    Join Date
    May 2002
    Posts
    10,943

    Re: Save scroll position

    Well, there is no reason why the parent node should affect this scenario. I assume you are checking the form results on the server-side. Are the results the same? What happens if you change the table's padding and spacing?

    What if instead of using the event catching, you tried grabbing the element?

    Code:
    function saveScroll(){
      var pos = document.getElementById('hdnScrollPos');
      var theScroll = document.getElementById('divScroll');
      pos.value = theScroll;
    }
    If the post was helpful...Rate it! Remember to use [code] or [php] tags.

  3. #3
    Join Date
    Sep 2004
    Posts
    65

    Re: Save scroll position

    I catch the event because the saveScroll function can be shared between multiple scrolling grids. I verified that all elements exist when the script is called, and they all contain valid values....

    I've figured out what was happening though (I think...). Since the script to gridLoad was fired immediately after the </div> tag, the parent table was not finished rendering. So, while all elements existed in the DOM, they were not yet rendered. My script fired without a problem, then the page finishes rendering... That is why my scroll position was not being maintained... I needed to have the script fire in <body onload=gridLoad('divScroll','hdnScrollPos')> . Since I couldn't modify the body tag, I had to find some other way..

    I came up with the following script to add scripts to fire after the page is rendered. addLoadScript...

    Code:
    <%@ Page Language="vb" AutoEventWireup="false" Codebehind="ScrollTest.aspx.vb" Inherits="AnotherTest.ScrollTest"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
      <HEAD>
        <title>ScrollTest</title>	
        <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
        <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
        <meta name=vs_defaultClientScript content="JavaScript">
        <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body >
      <script language="javascript">
      function addLoadScript(script)
      {
    	if (window.onload == null)
    	{
    		window.onload=new Function(script);
    	}
    	else
    	{
    	
    		var oldscript = window.onload.toString();
    		if (oldscript.substring(0,8) == 'function')
    		{
    			var start = oldscript.indexOf('{');
    			var end = oldscript.lastIndexOf('}');
    			oldscript = oldscript.substring(start + 1, end);
    			oldscript = Trim(oldscript);
    			
    			if  (oldscript.charAt(oldscript.length - 1) != ';')
    			{
    				oldscript = oldscript + ';';
    			}
    			window.onload = new Function(oldscript + script);
    		}
    	}
    }
    
    function Trim(sInString) 
    {
    	sInString = sInString.replace( /^\s+/g, "" );
    	return sInString.replace( /\s+$/g, "" );
    }
    	
      function saveScroll()
      {
    	var pos = document.getElementById('hdnScrollPos');
    	pos.value = event.srcElement.scrollTop;
      }
      
      function gridLoad(gridID, posID)
      {
    	var el = document.getElementById(gridID);
    	if (el) 
    	{
    		alert(document.getElementById(posID).value);
    		el.scrollTop = document.getElementById(posID).value;
    	}
    	else
    	{
    		alert('not found');
    	}
      }
      </script>
    
        <form id="Form1" method="post" runat="server">
        <table>
        <tr>
        <td>
    		<INPUT id="hdnScrollPos" type=hidden runat="server" NAME="hdnScrollPos">
    		<div id="divScroll" style="OVERFLOW:auto;WIDTH:70px;HEIGHT:100px" onscroll="saveScroll()">
    			<table>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    				<tr>
    					<td>1</td>
    					<td>A</td>
    				</tr>
    				<tr>
    					<td>2</td>
    					<td>B</td>
    				</tr>
    				<tr>
    					<td>3</td>
    					<td>C</td>
    				</tr>
    				<tr>
    					<td>4</td>
    					<td>D</td>
    				</tr>
    				<tr>
    					<td>5</td>
    					<td>E</td>
    				</tr>
    			</table>
    		</div>
    			
    			<script language="javascript">addLoadScript('alert("1")');</script>
    			<script language="javascript">addLoadScript('gridLoad("divScroll","hdnScrollPos");');</script>
    			<script language="javascript">addLoadScript('alert("2");');</script>
    			
    		<asp:Button id=Button1 runat="server" Text="PostBack"></asp:Button></td>
    		</tr>
    		</table>
    	
        </form>
    
    	
      </body>
    </HTML>
    This was a tough one for me to solve, as I'm weak with javascript.

    Thanks,
    Ranthalion

  4. #4
    Join Date
    May 2002
    Posts
    10,943

    Re: Save scroll position

    If you don't have other things onload, which it appears you don't, then you can make it easier on yourself.

    Code:
    <body onload="gridLoad("divScroll","hdnScrollPos")">
    
    or
    
    <script type="text/javascript">
    window.onload = gridLoad("divScroll","hdnScrollPos");
    </script>
    If the post was helpful...Rate it! Remember to use [code] or [php] tags.

  5. #5
    Join Date
    Sep 2004
    Posts
    65

    Re: Save scroll position

    In this example, you are correct, but I am developing a server control, so I cannot access or modify the body tag with it. Also, if the end user has assigned something to onload, I certainly would not want to overwrite it.

  6. #6
    Join Date
    May 2002
    Posts
    10,943

    Re: Save scroll position

    Okay. Sounds good. I could not tell those things from the examples posted.
    If the post was helpful...Rate it! Remember to use [code] or [php] tags.

  7. #7
    Join Date
    Sep 2004
    Posts
    65

    Re: Save scroll position

    Ah. Sorry.

    I tried to make the example easy to follow because my control's code is complex and long. I actually went through the same train of thoughts that you recommended. That's what led me to the answer I ultimately implemented.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured