payload: {"action":"created","comment":{"url":"https://api.github.com/repos/coveo/search-ui/pulls/comments/362103147","pull_request_review_id":337247152,"id":362103147,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDM2MjEwMzE0Nw==","diff_hunk":"@@ -0,0 +1,82 @@\n+import { Assert } from '../misc/Assert';\n+import { ResultListEvents, IDisplayedNewResultsEventArgs } from '../events/ResultListEvents';\n+import { QueryStateModel } from '../models/QueryStateModel';\n+import { $$ } from '../utils/Dom';\n+import { Logger } from '../misc/Logger';\n+\n+/**\n+ * This class is instantiated on the root of {@link SearchInterface}\n+ * if the {@link SearchInterface.options.enableScrollRestoration} option is set to true.\n+ *\n+ * Its job is to wait until the search results are displayed and the page height is long enough to\n+ * restore to the last scroll position. It'll wait for up to `restorationTimeOutInMs` milliseconds for the page to reach its height.\n+ *\n+ * This is useful when back and forth navigation between the search interface and results is needed on the same tab.\n+ *\n+ */\n+\n+export class ScrollRestorationController {\n+  public static stateAttributeName: string = 'yoffset';\n+  /**\n+   * Specifies the max amount of time to wait to restore the last scroll position.\n+   */\n+  public restorationTimeOutInMs: number = 5000;\n+\n+  private defaultYOffset: number = 0;\n+  private tryToScrollIntervalInMs: number = 50;\n+  private timeoutHandle = null;\n+\n+  constructor(public element: HTMLElement, public window: Window, public queryStateModel: QueryStateModel) {\n+    Assert.exists(this.queryStateModel);\n+\n+    this.initStateAttribute();\n+\n+    this.window.addEventListener('beforeunload', () => this.saveScrollPositionInState());\n+    $$(this.element).on(ResultListEvents.newResultsDisplayed, (event: Event, args: IDisplayedNewResultsEventArgs) =>\n+      this.handleNewResultsDisplayed(args)\n+    );\n+  }\n+\n+  private initStateAttribute() {\n+    this.queryStateModel.registerNewAttribute(ScrollRestorationController.stateAttributeName, this.defaultYOffset);\n+  }\n+\n+  private saveScrollPositionInState() {\n+    this.queryStateModel.set(ScrollRestorationController.stateAttributeName, this.window.pageYOffset);","path":"src/controllers/ScrollRestorationController.ts","position":45,"original_position":45,"commit_id":"be4cad49702bfd853f5503dc2e856216e5f28b9f","original_commit_id":"be4cad49702bfd853f5503dc2e856216e5f28b9f","user":{"login":"ThibodeauJF","id":4923043,"node_id":"MDQ6VXNlcjQ5MjMwNDM=","avatar_url":"https://avatars0.githubusercontent.com/u/4923043?v=4","gravatar_id":"","url":"https://api.github.com/users/ThibodeauJF","html_url":"https://github.com/ThibodeauJF","followers_url":"https://api.github.com/users/ThibodeauJF/followers","following_url":"https://api.github.com/users/ThibodeauJF/following{/other_user}","gists_url":"https://api.github.com/users/ThibodeauJF/gists{/gist_id}","starred_url":"https://api.github.com/users/ThibodeauJF/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ThibodeauJF/subscriptions","organizations_url":"https://api.github.com/users/ThibodeauJF/orgs","repos_url":"https://api.github.com/users/ThibodeauJF/repos","events_url":"https://api.github.com/users/ThibodeauJF/events{/privacy}","received_events_url":"https://api.github.com/users/ThibodeauJF/received_events","type":"User","site_admin":false},"body":"Yes it looks kind of weird to constantly update the QSM with the scroll position, it's also not something you want to pass over to someone if you send them a link.","created_at":"2019-12-30T21:42:38Z","updated_at":"2019-12-30T21:42:39Z","html_url":"https://github.com/coveo/search-ui/pull/1337#discussion_r362103147","pull_request_url":"https://api.github.com/repos/coveo/search-ui/pulls/1337","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/coveo/search-ui/pulls/comments/362103147"},"html":{"href":"https://github.com/coveo/search-ui/pull/1337#discussion_r362103147"},"pull_request":{"href":"https://api.github.com/repos/coveo/search-ui/pulls/1337"}},"in_reply_to_id":362097506},"pull_request":{"url":"https://api.github.com/repos/coveo/search-ui/pulls/1337","id":358156530,"node_id":"MDExOlB1bGxSZXF1ZXN0MzU4MTU2NTMw","html_url":"https://github.com/coveo/search-ui/pull/1337","diff_url":"https://github.com/coveo/search-ui/pull/1337.diff","patch_url":"https://github.com/coveo/search-ui/pull/1337.patch","issue_url":"https://api.github.com/repos/coveo/search-ui/issues/1337","number":1337,"state":"open","locked":false,"title":"JSUI-2751 Reposition result page to click result on \"Back\" click","user":{"login":"rdeandaCoveo","id":58610077,"node_id":"MDQ6VXNlcjU4NjEwMDc3","avatar_url":"https://avatars1.githubusercontent.com/u/58610077?v=4","gravatar_id":"","url":"https://api.github.com/users/rdeandaCoveo","html_url":"https://github.com/rdeandaCoveo","followers_url":"https://api.github.com/users/rdeandaCoveo/followers","following_url":"https://api.github.com/users/rdeandaCoveo/following{/other_user}","gists_url":"https://api.github.com/users/rdeandaCoveo/gists{/gist_id}","starred_url":"https://api.github.com/users/rdeandaCoveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rdeandaCoveo/subscriptions","organizations_url":"https://api.github.com/users/rdeandaCoveo/orgs","repos_url":"https://api.github.com/users/rdeandaCoveo/repos","events_url":"https://api.github.com/users/rdeandaCoveo/events{/privacy}","received_events_url":"https://api.github.com/users/rdeandaCoveo/received_events","type":"User","site_admin":false},"body":"For this story, I've created a class called `ScrollRestorationController` that takes care of restoring the last scroll position when navigating back to the search interface. My approach was:\r\n\r\n- Saving the yOffset to the state on unload. I did it on unload and not on result clicked, because maybe users are leaving the page to go to any other page on the site, like shopping cart.\r\n- When results are loaded, it \"polls\" for the page height until it's long enough or up to a time limit, that may be changed thru the `restorationTimeOutInMs` property on the controller. It seems to be the simplest approach as the document height depends on many things (css, web fonts, resource prioritization, etc.)\r\n- I prevent scroll restoration if the result list has infinite scrolling enabled, as right now the search interface doesn't preserve any state related to infinite scrolling, but I think it would be cool. \r\n\r\nDo you think the class should be a public property on the search interface or leave it internal and expose another component property to set the waiting time out?. I understand that, if possible, you try to avoid adding too many configuration options to components, but maybe in this case makes sense as there is no other need to have this controller public on the `SearchInterface`.\r\n\r\nBrowsers have a Back-Forward cache that supposedly caches the html and javascript state when the user leaves the page, but it doesn't work if the `unload` or `beforeunload` events are used. And those are used in the codebase, I think that's why the search interface is not preserving the scroll position. See https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching or https://developers.google.com/web/updates/2019/02/back-forward-cache\r\n\r\n* Still unit tests missing.\r\n\r\nhttps://coveord.atlassian.net/browse/JSUI-2751","created_at":"2019-12-30T16:25:13Z","updated_at":"2019-12-30T21:42:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9cdc382a42db21acb10f854dc288a0cbadcee72e","assignee":null,"assignees":[],"requested_reviewers":[{"login":"samisayegh","id":5565841,"node_id":"MDQ6VXNlcjU1NjU4NDE=","avatar_url":"https://avatars2.githubusercontent.com/u/5565841?v=4","gravatar_id":"","url":"https://api.github.com/users/samisayegh","html_url":"https://github.com/samisayegh","followers_url":"https://api.github.com/users/samisayegh/followers","following_url":"https://api.github.com/users/samisayegh/following{/other_user}","gists_url":"https://api.github.com/users/samisayegh/gists{/gist_id}","starred_url":"https://api.github.com/users/samisayegh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samisayegh/subscriptions","organizations_url":"https://api.github.com/users/samisayegh/orgs","repos_url":"https://api.github.com/users/samisayegh/repos","events_url":"https://api.github.com/users/samisayegh/events{/privacy}","received_events_url":"https://api.github.com/users/samisayegh/received_events","type":"User","site_admin":false},{"login":"fbeaudoincoveo","id":23503066,"node_id":"MDQ6VXNlcjIzNTAzMDY2","avatar_url":"https://avatars0.githubusercontent.com/u/23503066?v=4","gravatar_id":"","url":"https://api.github.com/users/fbeaudoincoveo","html_url":"https://github.com/fbeaudoincoveo","followers_url":"https://api.github.com/users/fbeaudoincoveo/followers","following_url":"https://api.github.com/users/fbeaudoincoveo/following{/other_user}","gists_url":"https://api.github.com/users/fbeaudoincoveo/gists{/gist_id}","starred_url":"https://api.github.com/users/fbeaudoincoveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fbeaudoincoveo/subscriptions","organizations_url":"https://api.github.com/users/fbeaudoincoveo/orgs","repos_url":"https://api.github.com/users/fbeaudoincoveo/repos","events_url":"https://api.github.com/users/fbeaudoincoveo/events{/privacy}","received_events_url":"https://api.github.com/users/fbeaudoincoveo/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/coveo/search-ui/pulls/1337/commits","review_comments_url":"https://api.github.com/repos/coveo/search-ui/pulls/1337/comments","review_comment_url":"https://api.github.com/repos/coveo/search-ui/pulls/comments{/number}","comments_url":"https://api.github.com/repos/coveo/search-ui/issues/1337/comments","statuses_url":"https://api.github.com/repos/coveo/search-ui/statuses/be4cad49702bfd853f5503dc2e856216e5f28b9f","head":{"label":"coveo:JSUI-2751","ref":"JSUI-2751","sha":"be4cad49702bfd853f5503dc2e856216e5f28b9f","user":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars2.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"repo":{"id":58133471,"node_id":"MDEwOlJlcG9zaXRvcnk1ODEzMzQ3MQ==","name":"search-ui","full_name":"coveo/search-ui","private":false,"owner":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars2.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/coveo/search-ui","description":"Coveo Search UI framework","fork":false,"url":"https://api.github.com/repos/coveo/search-ui","forks_url":"https://api.github.com/repos/coveo/search-ui/forks","keys_url":"https://api.github.com/repos/coveo/search-ui/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/search-ui/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/search-ui/teams","hooks_url":"https://api.github.com/repos/coveo/search-ui/hooks","issue_events_url":"https://api.github.com/repos/coveo/search-ui/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/search-ui/events","assignees_url":"https://api.github.com/repos/coveo/search-ui/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/search-ui/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/search-ui/tags","blobs_url":"https://api.github.com/repos/coveo/search-ui/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/search-ui/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/search-ui/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/search-ui/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/search-ui/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/search-ui/languages","stargazers_url":"https://api.github.com/repos/coveo/search-ui/stargazers","contributors_url":"https://api.github.com/repos/coveo/search-ui/contributors","subscribers_url":"https://api.github.com/repos/coveo/search-ui/subscribers","subscription_url":"https://api.github.com/repos/coveo/search-ui/subscription","commits_url":"https://api.github.com/repos/coveo/search-ui/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/search-ui/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/search-ui/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/search-ui/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/search-ui/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/search-ui/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/search-ui/merges","archive_url":"https://api.github.com/repos/coveo/search-ui/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/search-ui/downloads","issues_url":"https://api.github.com/repos/coveo/search-ui/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/search-ui/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/search-ui/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/search-ui/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/search-ui/labels{/name}","releases_url":"https://api.github.com/repos/coveo/search-ui/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/search-ui/deployments","created_at":"2016-05-05T13:41:09Z","updated_at":"2019-12-30T19:16:21Z","pushed_at":"2019-12-30T20:47:03Z","git_url":"git://github.com/coveo/search-ui.git","ssh_url":"git@github.com:coveo/search-ui.git","clone_url":"https://github.com/coveo/search-ui.git","svn_url":"https://github.com/coveo/search-ui","homepage":null,"size":155524,"stargazers_count":76,"watchers_count":76,"language":"TypeScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":57,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":7,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":57,"open_issues":7,"watchers":76,"default_branch":"master"}},"base":{"label":"coveo:master","ref":"master","sha":"5c36e03e8755eaf04dbaf44ddd70843d8695e7f1","user":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars2.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"repo":{"id":58133471,"node_id":"MDEwOlJlcG9zaXRvcnk1ODEzMzQ3MQ==","name":"search-ui","full_name":"coveo/search-ui","private":false,"owner":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars2.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/coveo/search-ui","description":"Coveo Search UI framework","fork":false,"url":"https://api.github.com/repos/coveo/search-ui","forks_url":"https://api.github.com/repos/coveo/search-ui/forks","keys_url":"https://api.github.com/repos/coveo/search-ui/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/search-ui/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/search-ui/teams","hooks_url":"https://api.github.com/repos/coveo/search-ui/hooks","issue_events_url":"https://api.github.com/repos/coveo/search-ui/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/search-ui/events","assignees_url":"https://api.github.com/repos/coveo/search-ui/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/search-ui/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/search-ui/tags","blobs_url":"https://api.github.com/repos/coveo/search-ui/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/search-ui/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/search-ui/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/search-ui/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/search-ui/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/search-ui/languages","stargazers_url":"https://api.github.com/repos/coveo/search-ui/stargazers","contributors_url":"https://api.github.com/repos/coveo/search-ui/contributors","subscribers_url":"https://api.github.com/repos/coveo/search-ui/subscribers","subscription_url":"https://api.github.com/repos/coveo/search-ui/subscription","commits_url":"https://api.github.com/repos/coveo/search-ui/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/search-ui/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/search-ui/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/search-ui/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/search-ui/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/search-ui/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/search-ui/merges","archive_url":"https://api.github.com/repos/coveo/search-ui/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/search-ui/downloads","issues_url":"https://api.github.com/repos/coveo/search-ui/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/search-ui/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/search-ui/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/search-ui/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/search-ui/labels{/name}","releases_url":"https://api.github.com/repos/coveo/search-ui/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/search-ui/deployments","created_at":"2016-05-05T13:41:09Z","updated_at":"2019-12-30T19:16:21Z","pushed_at":"2019-12-30T20:47:03Z","git_url":"git://github.com/coveo/search-ui.git","ssh_url":"git@github.com:coveo/search-ui.git","clone_url":"https://github.com/coveo/search-ui.git","svn_url":"https://github.com/coveo/search-ui","homepage":null,"size":155524,"stargazers_count":76,"watchers_count":76,"language":"TypeScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":57,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":7,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":57,"open_issues":7,"watchers":76,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coveo/search-ui/pulls/1337"},"html":{"href":"https://github.com/coveo/search-ui/pull/1337"},"issue":{"href":"https://api.github.com/repos/coveo/search-ui/issues/1337"},"comments":{"href":"https://api.github.com/repos/coveo/search-ui/issues/1337/comments"},"review_comments":{"href":"https://api.github.com/repos/coveo/search-ui/pulls/1337/comments"},"review_comment":{"href":"https://api.github.com/repos/coveo/search-ui/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/coveo/search-ui/pulls/1337/commits"},"statuses":{"href":"https://api.github.com/repos/coveo/search-ui/statuses/be4cad49702bfd853f5503dc2e856216e5f28b9f"}},"author_association":"CONTRIBUTOR"}}
other: {"actor":{"display_login":"ThibodeauJF"}}