Closed Bug 16806 Opened 26 years ago Closed 25 years ago

Save scroll position in session history

Categories

(Core :: DOM: Navigation, defect, P3)

defect

Tracking

()

VERIFIED FIXED

People

(Reporter: pollmann, Assigned: pollmann)

References

(Blocks 1 open bug)

Details

(Whiteboard: [nsbeta2+][Will be minus on 6/15] fix in hand)

Need to implement nsIStatefulFrame for the scroll frame.
Status: NEW → ASSIGNED
Will just implementing nsIStatefulFrame provide adequate results for named anchors? That is, if you move from one named anchor to another, and back, will you go to the remembered position? (Or was this bug about scroll position in textareas and iframes, etc.?) See my comments on bug 16379 and bug 3891.
*** Bug 3891 has been marked as a duplicate of this bug. ***
*** Bug 16379 has been marked as a duplicate of this bug. ***
The way I'm attacking it now is to store scroll position for each nsScrollPortFrame. I don't see how moving to named anchors will be any different than just preserving the session history - when a link is clicked, you are going to a different URL, even if that happens to be a named anchor on the same page. This should work now, no? There is one known problem if I store the scroll position by pixel offset, as I am currently implementing. If the width of the window is resized, the position in the document may be different, due to a reflow. I don't see an easy fix for this yet.
Played around with the resizing issue in a few browsers, and based on what I saw, there may not be an easy fix for the resizing known issue at all, based on pixel offsets. The best you could do would be to apply two different factors based on height and width change. Two factors would be needed because changes in height have a much greater effect than changes in width. Also, this would have to based on canvas size, not window size. The sidebar also complicates things. To do this, it would probably be necessary to save the canvas size for each entry in the session history. If the canvas size were saved, a simple workaround (albeit one that may strike many people as weird) would be to resize the browser as the session history is moved through, so that the canvas size is the same that it was when each page was last viewed. The pixel offsets would be correct then for sure! But this is probably too weird. There is another workaround for this issue: store the page position based on an integer pixel offest from the top of the topmost DOM node on the page (integer because it could be off the top of the page). I'm guessing this would be harder, but who knows? Note that the scroll position would still need to be stored as a pixel offset as a backup, in case the page in the session history has changed and that node on the DOM tree no longer exists!
How is the offset remembered for when we do reflows? When we change to an alternate stylesheet, the entire window is redrawn but the position is not reset to the top -- is the way that is done even remotely portable to the session history?
I think it's remembered as a pixel offset from the top - that's how it looks, anyway. There's existing (but somewhat buggy) code (for event handling) to get the frame at a given point, and existing code to scroll to a given frame. The problem with a better solution is knowing what point will give the correct frame (or probably finding the frame some other way).
We could: 1) Get the current scroll offset 2) Get the frame at those coordinates (top left corner of view) 3) Find coordinates of that frame. 4) Store 2 and 1 minus 3 (offset into that frame) as the scroll state When restoring we set the scroll offset to the coordinates of frame 2 (which may be different due to a resize) plus the offset into that frame. Another possibility would be to get the frame in the center of the view, and scroll that into the center of the view when restoring. These seems more user friendly than pixel offsets, but also could require a lot of computation. This logic would be used for every scrollbar visible on the web page when it was left, including the scrollbars for listboxes and textareas. For a first pass, I'm going to just store pixel offsets. Once that is working, I'll look at optimizing the offset logic - perhaps to what I just mentioned, or a rough approximation that requires less computation.
The problem with what you suggest is that you can easily hit a gap between frames and end up with the BODY frame when you ask for the frame at a given point. Furthermore, you don't want to be messed up by floaters or fixed positioned elements or other such things.
Thanks. Yes, there are several issues now that I think about that - especially the first suggestion I wrote is flawed - what if it got an inline frame that was at the beginning of a line but then reflowed to the far right side of the line. The user would be viewing a big blank document. More thinking required on this. Is pixel offsets is acceptable to everyone as a first pass? :)
It's certainly better than nothing! :-)
Blocks: 19261
*** Bug 18658 has been marked as a duplicate of this bug. ***
*** Bug 19548 has been marked as a duplicate of this bug. ***
*** Bug 21739 has been marked as a duplicate of this bug. ***
Target Milestone: M14
Marking this feature for M14.
*** Bug 23079 has been marked as a duplicate of this bug. ***
Blocks: 24206
*** Bug 25304 has been marked as a duplicate of this bug. ***
*** Bug 26122 has been marked as a duplicate of this bug. ***
Keywords: beta1
Can we live without this for beta1?
Whiteboard: [PDT-]
Do you want beta1 to impress people?
*** Bug 27372 has been marked as a duplicate of this bug. ***
I honestly could deal without this for beta1, but it definitely should not slip beta2.
Moving non PDT+ bugs out.
Target Milestone: M14 → M15
*** Bug 24852 has been marked as a duplicate of this bug. ***
*** Bug 29967 has been marked as a duplicate of this bug. ***
*** Bug 30263 has been marked as a duplicate of this bug. ***
Updating QA contact.
Component: Browser-General → History
QA Contact: leger → claudius
*** Bug 30111 has been marked as a duplicate of this bug. ***
*** Bug 33704 has been marked as a duplicate of this bug. ***
ftp/file expantion state also needs saving, might be common code: see bug 33703
*** Bug 33965 has been marked as a duplicate of this bug. ***
*** Bug 34141 has been marked as a duplicate of this bug. ***
*** Bug 34523 has been marked as a duplicate of this bug. ***
Moving out to M17.
Target Milestone: M15 → M17
I really missed seeing this in PR1. I surely hope it doesn't get bumped indefinitely. At HotBot.com we gets lots of user feedback about this and only can tell them to use IE5 if this feature is important to them.
Rescheduling
Target Milestone: M17 → M16
*** Bug 35729 has been marked as a duplicate of this bug. ***
What about storing a certain amount of the source file at the position in the history. Then when the going back, search for the stored text in the source and set the scroll position accordingly? The hard part would be writing the code to translate a linenumber in the source to a pixel coridinate for the scroll frame.
That doesn't explain which position in the document to use. I was thinking a bit about an algorithm for this, and I wrote down some notes somewhere. (If you're interested, I can try and find the notes.) But the basic idea was this: * pick n points (say n=10) across the top of the scrolling view (or maybe a hair below the top), kinda like this: * * * * * * * * * * and then find the frame that is the closest common ancestor of at least a*n of them (say, a=0.5), and store the position in twips relative to that frame (or, really, the a way of finding the content node for that frame). * have special cases for being at the top or the bottom (and of course hitting it) * I know I have some other things to say here... This algorithm could also be used during a resize-reflow. It would be good to use the original remembered position for a series of resizes - that is, on a drag-resize (or even a series thereof), one would want to use the original remembered position throughout, rather than continually recalculate. This could be done by clearing the remembered position when the view is scrolled. One might also need to make special exceptions for when scrolling views were within scrolling views (e.g., IFRAME), since the reference frame (probably) shouldn't be within another scrolling view (or perhaps it's not a problem?).
*** Bug 36070 has been marked as a duplicate of this bug. ***
*** Bug 36477 has been marked as a duplicate of this bug. ***
*** Bug 36543 has been marked as a duplicate of this bug. ***
Removing 'beta1' keyword since beta 1 is long gone.
Keywords: beta1
Oops, I noticed there's a 'nsbeta2' keyword as well. Putting that in.
Keywords: nsbeta2
*** Bug 37390 has been marked as a duplicate of this bug. ***
Depends on: 35566
Clearing Status Whiteboard since `beta1' has been replaced by `nsbeta2'. I really hope that [PDT-] was left over from `beta1'...
Whiteboard: [PDT-]
*** Bug 38452 has been marked as a duplicate of this bug. ***
From a usability point of view, I think it's most obvious if the top of the content frame is kept constant, rather than the middle. Therefore, I suggest ... * As soon as the frame either {starts to go to a new location} or {is resized, whether because of window resizing, sidebar opening, or whatever}, define an anchor point for the original layout at (0 + left margin of BODY in pixels, 0 + top margin of BODY in pixels). * Find the object boundary in the same layout frame which is nearest to the anchor point in the northwest direction. `Object boundary' here could be the border between two words, or between two images, or a plugin and a word, or whatever. * Record both the identity of the object boundary (however you like -- the number of the relevant character in the source code might work, unless of course you're viewing an image) and the x and y offsets from that object boundary to the anchor point. So for example, I might end up with an anchor point that was `3 pixels south and 5 pixels east of the boundary between the 785th and 786th elements in the page'. * Whenever that location is returned to, or the window is resized, position the layout so that, in order of priority: - the vertical position of the anchor point is exactly the same as it was originally - the horizontal position of the anchor point is as close as possible to what it was originally. * Do this for any frames and iframes in the page, as well as for the document as a whole. * Only define the anchor point just before the *first* time the frame is resized while it is shown, not every time. That way you will avoid the possibility of the position drifting away from the original after repeated resizing. * Exactly how this method should deal with languages which aren't read in the {left-to-right, top-to-bottom} direction is left as an exercise for the reader. Example: let's say I'm in an HTML page, and the first completely visible line at the top of the screen reads | | razed and they shall be scorched to the earth. Their tags shall When I resized the window, the content would always be scrolled so that the word `razed' had exactly the same vertical offset from the top of the scrollport as it did originally. (The horizontal position would obviously differ because of the different wrapping of the paragraph.) Does this make any sense?
To some degree, but focusing on just the NW corner will mess things up when there are left-floating elements involved. I proposed that we worry about the entire top of the viewport.
Putting on [nsbeta2+][6/01] radar. This work must be done by 06/01 or we may pull this for PR2.
Whiteboard: [nsbeta2+][6/01]
Target Milestone: M16 → M17
Not going in before M16 closes tonight.
*** Bug 40104 has been marked as a duplicate of this bug. ***
With 24 dups, this thing should be mostfreq. *SPAM* - adding mostfreq keyword to bugs with loads of dupes. Please aid this effort by adding this keyword to any bugs with more than 15 DUPEs.
Keywords: mostfreq
*** Bug 40505 has been marked as a duplicate of this bug. ***
*** Bug 40749 has been marked as a duplicate of this bug. ***
I have an implementation idea for this. When we need to store the scroll position, could we store the XPointer to the topmost (as in the visible area) DOM element? Of course we do not yet have any XPointer support, but suppose we did, would this work? I know that if we have scripts involved, the script may change the document between each load so much that that might break almost any attempt, but are there any other issues?
I have a fix in my tree for this that works for both Gfx and Native scrollbars. So far, all I've implemented is very basic scroll positioning (x,y pixel offsets). The fix was: Implement nsIStatefulFrame for nsScrollPortFrame for the gfx scrollbar case and nsScrollFrame for the native scrollbar case (implementations are identical) Expose nsFrameManager's CatureFrameStateFor and RestoreFrameStateFor as public methods and add an additional parameter to accept a fixed content id (scroll frames don't have any content associated with them. Capture frame state for the root scroll frame in PresShell::CaptureHistoryState and restore it in PresShell::EndLoad. Use a fixed content id. (I chose 1, but should probably come up with an enum or something like that) Not sure this will be approved for beta2 now that the deadline is passed, keep your fingers crossed! :)
Summary: Saving scroll position in session history → Save scroll position in session history
Whiteboard: [nsbeta2+][6/01] → [nsbeta2+][6/01] fix in hand
Due to slip in schedule, moving this bug from [6/01] to [Will be minus on 6/15] for fix deadline.
Whiteboard: [nsbeta2+][6/01] fix in hand → [nsbeta2+][Will be minus on 6/15] fix in hand
> So far, all I've implemented is very basic scroll positioning (x,y pixel... I made a slight improvement on this today. Instead of storing just x and y, also stored height and width of the frame *inside* the scroll frame. When returning to the page, I scale x and y proportionally to the new height and width: newx = oldx * newwidth / oldwidth newy = oldy * newheight / oldheight This gets us to within a few lines of where we were on even tough pages like: http://www.w3.org/MarkUp/ (Try scrolling to a choice place in Nav or IE, then going somewhere else, radically changing window width and returning - both apparently store pixel offsets, and you'll have to scroll to find your place!) Ideally, we should store a content pointer, but I don't have any ideas on how to easily implement this. (I don't think I'll have time to go the xpointer route...)
Just checked in the fix. To verify, go to any page. Scroll part way down. Go to any other page. Click back. You should see that you are at the same part of the page that you were at when you left the page. Thanks!
Status: ASSIGNED → RESOLVED
Closed: 25 years ago
Resolution: --- → FIXED
*** Bug 42914 has been marked as a duplicate of this bug. ***
VERIFIED Fixed in the 2000061908 builds on all platforms. note this fixes saving scroll position for back/forwqard but nor for reload. That issue is beingtracked separately in bug 40104 note: the username t8m@centrum.com is being truncated to t8m@centrum.c on the cc list by 4.x and bugzilla won't let me submit this bug as such so I had to remove it, sorry, I'll try to correct later.
Status: RESOLVED → VERIFIED
No longer blocks: 24206
This has now regressed and been reborn as bug 46877. I suggest we use our voting power to try and get this fixed again.
*** Bug 276007 has been marked as a duplicate of this bug. ***
Component: History: Session → Document Navigation
QA Contact: claudius → docshell
You need to log in before you can comment on or make changes to this bug.