On Tue, Apr 28, 2015 at 9:16 AM, Majid Valipour <maji...@google.com> wrote:
> On Mon, Apr 27, 2015 at 9:54 PM Jonas Sicking <jo...@sicking.cc> wrote:
>>
>> Jumping in at the end here.
>>
>> As I've said before, I like the general idea of giving pages more
>> control over scroll restoration, but I don't think we should tie this
>> to pushState()/replaceState()/onscroll.
>>
>> My proposal is instead that we add an API like
>>
>> history.restoreScroll = boolean;
>
>
> Interesting. I believe Simon has also proposed a similar API for which you
> can find my original objections here.
>
> One of my objections was that any proposed API should give developers
> control of scroll restoration per individual history entry. Initially I
> assumed a single boolean flag cannot provide that control but now I believe
> what you are proposing here can in fact provide per-entry control. More on
> this later.
>
> My other objection was that because scroll restoration behaviour is
> ultimately tied to a specific history entry, the API to control it should
> reflect this underlying fact. IMO a flag on history object hides this fact
> while original proposal does not.
>
> I understand that for pages that do not create any state other than their
> default initial state (e.g., infinite scrollers) setting
> history.restoreScroll is simpler than using
> history.replaceState({restorScroll: false}). But I think this additional
> complexity is not prohibitive and can be justified when the upside is an API
> that better explains the underlying behaviour and is simpler for pages that
> do create multiple states using history.pushState.

I agree that the difference between

history.restoreScroll = false;
and
history.replaceState({restoreScroll: false});

is not that big and mainly comes down to taste. I like the former more.

>> This property would default to true. Whenever pushState() is called,
>> or the user navigates away from the current page, for example by
>> clicking a <a href=...> the value of history.restoreScroll is copied
>> into the session-history-entry data that the browser keeps internally.
>> As soon as the new session-history-entry is created, restoreScroll is
>> set to true again.
>
> So history.restoreScroll is copied into current history entry anytime a new
> history entry is created (or replaced). If my reading is correct then this
> makes sense and it can give per history entry control. The value of
> history.restoreScroll is reset to its default when a new document is loaded.
>
> Consider this case where page A uses pushState once and then navigates to
> page B. This creates three history entries: 2 for A and one for B.
>
> A  -->  Ai  (*)   ==> B
> where:
> -->  pushState
> ==> navigation to new page
> (*) history.restoreScroll is set to 'false'
>
> This is what I think should happen:
> on A load:  history.restoreScroll is reset to default value: TRUE.
>                   history entry is created for A.
>
> on -->:        current entry (A) is updated with current restoreScroll: TRUE
>                    history entry is created for Ai
>
> on (*):          history.restoreScroll is set to 'FALSE'.
>
> on ==>:        current entry (Ai) is updated with current restoreScroll:
> FALSE
>
> on B load:  history.restoreScroll is reset to default value: TRUE
>                    history entry for B is created.
>
> A gets TRUE
> Ai gets FALSE
> B gets TRUE

Agreed.

>> Additionally we could enable passing a boolean to pushState(), and
>> this value would be used as the new initial value for restoreScroll.
>> So something like pushState({ url: myURL, restoreScroll: false });.
>> This would simply be syntax sugar for |pushState("", "", myURL);
>> history.restoreScroll = false;|.
>
> It is a nice syntax sugar but I don't feel it adds enough value to justify
> doing this at browser level. It can be done in Javascript by
> framework/poly-fill authors.

I'm fine either way.

>> I think that's all that's needed.
>
> Yes. Both APIs are equally expressive and one may be built on top of the
> other.
>
> I suggest two minor changes though:
>
> 1. We specifically proposed using a dictionary for options with scroll
> restoration being one of its parameters. This allows us to add additional
> history entry control parameters in the future. For example we can expose
> zoom restoration similarly if there is enough demand.
> 2. As suggested earlier in the thread it is better to use a name that
> suggests more strongly that the author is expected to restore the position
> themselves.
>
> So:
>
> history.options = {
>    willRestoreScroll =  false
> }

I'm not strongly opinionated on naming. Are there other APIs in the
platform which are named similarly?

>> In order to make it easier for pages we could also expose a
>> history.restoredScrollPosition which is a readonly property which the
>> UA writes to any time it restores a session history entry, which is
>> the scroll position that it would have restored scrolling to if the
>> page hadn't disabled scroll restoration for the given session history
>> entry.
>>
>> This is isn't strictly needed though since the page can simply use
>> sessionStorage and update the scroll position in a onscroll handler.
>
>
> Storing position is sessionStorage works well. It has the advantage that the
> the same logic can handle scroll restoration for both history and
> non-history navigations (e.g., same page being loaded as a result of
> clicking back button or a link).

But what happens if the user navigates

A.html ===> B.html ===> A.html ===> C.html

How do you ensure that the second A.html page doesn't overwrite the
saved scroll position of the first A.html session history entry? I.e.
how do you ensure that you use different key names in the
sessionStorage?

> Providing scroll position is nice to have but not required. I think it
> requires additional spec work to exactly define the behaviour of scroll
> restoration across different browsers. Right now different vendors have
> different behaviour when it comes to restoring scroll position for iframes,
> and inner scrollables etc. So it is not really clear how exactly this
> 'scroll position' should look like.
>
> Getting this boolean flag should not be blocked on providing scroll
> position.

Agreed.

/ Jonas

Reply via email to