Re-sending my response with my member email address to ensure it is
included in the mailing list archive. Sorry about duplication :(.

---------- Forwarded message ---------
From: Majid Valipour <>
Date: Wed, Mar 25, 2015 at 8:22 PM

On Wed, Mar 25, 2015 at 4:32 PM Jonas Sicking <> wrote:

> Is this really something we should tie to the pushState/replaceState API?
> It seems like websites that lazily add more content as the user scroll
> down, like the facebook feed or twitter feed, might not use
> pushState/replaceState, but would still like to handle restoring
> scroll position themselves.
> / Jonas
History spec models history entry as having two types of states: 1)user
state, 2)user agent defined state. Scroll position is part of the user agent
defined state[1] which may also include form data, zoom factor, etc.  During
history navigation when an entry is poped, the user agent defined state is
automatically restored while the application is responsible for restoring
user state.

Both history.pushState() and history.replaceState() are really meant to
Javascript to manipulate history entries. They are currently limited to
modifying only the user state, url, and title of an entry. I think using
methods for controlling user agent defined states in addition to user state
a natural extension of their functionality and consistent with existing
history model where an entry contains two types of state.

The current proposal only suggests a control knob for scroll position but I
can definitely imagine providing additional knobs for other parts of user
agent state such as form data, zoom factor, etc. The dictionary is
used to provide this flexibility.

The example of sites that you mentioned can simply use a replaceState. This
does not  require them to opt into fully managing their navigation using
pushState or creating new URLs client side.

window.addEventListener('popstate', s => {
history.replaceState(null, null, null, {restoreScroll:false})

Note that the browser always creates a default history entry on page load.
this case, history.replaceState updates this default history entry and
its default user agent state to no longer have scroll restoration.

This becomes even more elegant if we adopt the above proposal to pass a
dictionary i.e. history.replace({restoreScroll:false}).

[1] "Each session history entry consists, at a minimum, of a URL, and each
entry may in addition have a state object, a title, a Document object, form
data, a scroll position, and other information associated with it."

> On Wed, Mar 25, 2015 at 6:54 AM, Anne van Kesteren <>
> wrote:
> > On Thu, Mar 19, 2015 at 6:31 PM, Majid Valipour <>
> wrote:
> >> partial interface History {
> >>   void pushState(in any data, in DOMString title, in optional DOMString
> >> url, in optional StateOptions options);
> >>   void replaceState(in any data, in DOMString title, in optional
> DOMString
> >> url, in optional StateOptions options);
> >>   readonly attribute StateOptions options;
> >> };
> >>
> >> dictionary StateOptions {
> >> Boolean restoreScroll = true,
> >> }
> >
> > The only suggestion I have is that instead of having four-argument
> > methods we might want to consider introducing two new methods that
> > take a dictionary. E.g. history.push() and history.replace(). Giving
> > the page more control over the scroll position when navigating makes
> > sense to me.
> >
> >

Adding two new methods that take a dictionary provides a cleaner API. I also
think replace() and push() better capture their intended use which is to
manipulate the history *entry* as opposed to only the entry's user state. In
fact current method names are not exactly accurate as they manipulate not
the user state but also its title, and URL.

My only concern is to make sure that these new methods replace
history.pushState() and history.replaceState() in the spec. Otherwise I feel
the benefits of a cleaner API is not worth the additional confusion of
different methods for doing (almost) the same thing.


Reply via email to