{"action":"created","issue":{"url":"https://api.github.com/repos/algolia/algoliasearch-helper-js/issues/138","labels_url":"https://api.github.com/repos/algolia/algoliasearch-helper-js/issues/138/labels{/name}","comments_url":"https://api.github.com/repos/algolia/algoliasearch-helper-js/issues/138/comments","events_url":"https://api.github.com/repos/algolia/algoliasearch-helper-js/issues/138/events","html_url":"https://github.com/algolia/algoliasearch-helper-js/issues/138","id":93274472,"number":138,"title":"API proposal: url synchronisation","user":{"login":"vvo","id":123822,"avatar_url":"https://avatars.githubusercontent.com/u/123822?v=3","gravatar_id":"","url":"https://api.github.com/users/vvo","html_url":"https://github.com/vvo","followers_url":"https://api.github.com/users/vvo/followers","following_url":"https://api.github.com/users/vvo/following{/other_user}","gists_url":"https://api.github.com/users/vvo/gists{/gist_id}","starred_url":"https://api.github.com/users/vvo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vvo/subscriptions","organizations_url":"https://api.github.com/users/vvo/orgs","repos_url":"https://api.github.com/users/vvo/repos","events_url":"https://api.github.com/users/vvo/events{/privacy}","received_events_url":"https://api.github.com/users/vvo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-07-06T13:06:36Z","updated_at":"2015-07-06T13:28:13Z","closed_at":null,"body":"Following discussions and requests from #40 #127, given all the different implementations out there to maintain/set/read the search state in the url, I feel it's time to really tackle this.\r\n\r\nDoes it belongs to the helper? Given the number of time we had to implement it in many demos, I guess yes.\r\n\r\nIs this a problem to talk about browser specific need since our helper is [\"Universal\"](https://medium.com/@mjackson/universal-javascript-4761051b7ae9)? Seems no big deal since we can expose some feature only to the browser.\r\n\r\n## Goal\r\n\r\nWhen using the helper url synchronisation, we should be able to have a working refresh/back/forward browser button that will reset the page to where we were.\r\n\r\n## Examples\r\n\r\n### Simple usage\r\n\r\n```js\r\nvar helper = algoliasearchHelper(client, indexName, {\r\n  urlSync: true\r\n});\r\n```\r\n\r\n### Advanced usage: use `location.hash`\r\n\r\n```js\r\nvar helper = algoliasearchHelper(client, indexName, {\r\n  urlSync: {\r\n    useHash: true\r\n  }\r\n});\r\n```\r\n\r\n### Advanced usage: late activation\r\n\r\n```js\r\nvar helper = algoliasearchHelper(client, indexName);\r\n\r\n// ...\r\n\r\nhelper.urlSync([opts])\r\n```\r\n\r\n### Advanced usage: `helper.setStateFromURL([URL])`\r\n\r\nUseful when you want to manage everything by yourself. Or if you are\r\nserver-side.\r\n\r\nUsing the current url\r\n```js\r\nvar helper = algoliasearchHelper(client, indexName);\r\nhelper.setStateFromURL(); // reads the current URL\r\nhelper.search();\r\n```\r\n\r\nManually giving a URL (can be used server side)\r\n```js\r\nvar helper = algoliasearchHelper(client, indexName);\r\nhelper.setStateFromURL('q=salut&hitsPerPage=200'); // takes a manual url (partial or full url)\r\nhelper.search();\r\n```\r\n\r\n### Advanced usage: `helper.getStateAsQueryString([opts])`\r\n\r\nUseful when you want to manage everything by yourself.  Or if you are\r\nserver-side.\r\n\r\n```js\r\nvar helper = algoliasearchHelper(client, indexName, {\r\n  hitsPerPage: 200\r\n});\r\nhelper.search('salut');\r\n\r\n//...\r\n\r\nhelper.getStateAsQueryString();\r\n// q=salut&hitsPerPage=200\r\n```\r\n\r\n## Requirements\r\n\r\n- It should be possible to ask the helper to maintain the search state in the url (off by default)\r\n- use `location.search` by default (\"real\" query strings), and have an option switch to `location.hash`\r\n- use history API and provide the [necessary](http://caniuse.com/#feat=history) [fallback](https://github.com/devote/HTML5-History-API) for IE < 10\r\n- use a deep object query string formatter like [hapijs/qs](https://github.com/hapijs/qs)\r\n- only store the necessary state diff and not the full helper state in url\r\n- debounce the synchronisation to Xms so that we only push the state in the url when the user finished a serie of keystrokes\r\n- do not completely overwrite the current query string or hash, only overwrite known parameters and add everything else after\r\n  - so that a client using things like anchors or expecting a certain query string to always be there will not be surprised\r\n\r\n## Implementation flow\r\n\r\nOn the first page load, read the parameters from the url, merge them with all the parameters set until the first `helper.search()` call (those must be considered as defaults for the page).\r\n\r\nUse `history.replaceState()` on first page load. Then use pushState.\r\n\r\nAll the parameters sets before the first `helper.search()` call should be considered defaults and not to be set in the url since they are already in the page (diff)\r\n\r\nwhat do you think?\r\n"},"comment":{"url":"https://api.github.com/repos/algolia/algoliasearch-helper-js/issues/comments/118853897","html_url":"https://github.com/algolia/algoliasearch-helper-js/issues/138#issuecomment-118853897","issue_url":"https://api.github.com/repos/algolia/algoliasearch-helper-js/issues/138","id":118853897,"user":{"login":"vvo","id":123822,"avatar_url":"https://avatars.githubusercontent.com/u/123822?v=3","gravatar_id":"","url":"https://api.github.com/users/vvo","html_url":"https://github.com/vvo","followers_url":"https://api.github.com/users/vvo/followers","following_url":"https://api.github.com/users/vvo/following{/other_user}","gists_url":"https://api.github.com/users/vvo/gists{/gist_id}","starred_url":"https://api.github.com/users/vvo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vvo/subscriptions","organizations_url":"https://api.github.com/users/vvo/orgs","repos_url":"https://api.github.com/users/vvo/repos","events_url":"https://api.github.com/users/vvo/events{/privacy}","received_events_url":"https://api.github.com/users/vvo/received_events","type":"User","site_admin":false},"created_at":"2015-07-06T13:28:13Z","updated_at":"2015-07-06T13:28:13Z","body":"> helper.setStateFromURL($location.search())\r\n\r\nSo you want to manually set the state from URL but using an angularJS specific object notation (`$location.search()`)?\r\n\r\nI guess in this case either you let the helper sync the url for you (auto sync), or you manually set the state with `helper.setState`?\r\n\r\nAs we do not have specific helper builds for angular, how would I know that the call to `helper.setStateFromURL()` was given an angular.js $location.search() object? Query string to object format is not something standard. That's why dealing with strings on the API level is the easiest.\r\n\r\n> the Angular build should be able to use $location.search('q', state.query).search('facetFilters[]', 'foo:bar')... to change the URL\r\n\r\nThis is already doable right?"}}