changing window.location without triggering refresh - javascript

I have an AJAX form that submits GET requests. Because these are all GET requests these should be easily bookmark-able. Preferably I'd make my Ajax request, update the screen and then update window.location.href to be the URL for the new page.
Unfortunately this reloads the page. Is there any way I can get around this? Basically I'd like the URL bar to be a permalink bar, but it needs to be able to change to keep up with the state of the page.
window.location.hash is no good because that doesn't get sent to the server.

window.history.replaceState( {} , title, new_URL );
This will update the current page URL with a new one without refreshing.
Arguments:
Data object (must be one that could be serialized to text)
The new title of the changed window URL
The URL to change to (without refreshing)
The you could use the window.onpopstate = function(event){...} to listen to events when a user goes back or forward in the browser history and change things however you wish.

The hash is the way to go. Because, as you point out, changes to the hash don't get sent to the server, you have to send an async request to the server as well as updating the hash.
As a simple example, if your URL is http://server.com/page?id=4, when the user triggers the action you send an AJAX request for http://server.com/page?id=4, and set the page URL to http://server.com/page#id=4.
Furthermore, you have to have something to restore the state if the user reloads. This would usually be done by reading the hash value client-side and sending an async request to the server based on the state represented by the hash value.

if you want to do which works in current browser, you can't change window.location.href without reloading the page
your only option is to to change window.location.hash.
you can do that each time you make an ajax call. if you're using jquery, you can bind a function which update the hash each time an ajax call is made.
if you choose that you'll have to look for the hash on page load (actually don't know/think you can do that server side) and make that call to have your page on the state corresponding to the hash.
-- update
there is now an API which provide this functionality look for history.pushState, history.replaceState and window.onpopstate : https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#Adding_and_modifying_history_entries
it's not availlable everywhere yet ( http://caniuse.com/#feat=history ), there is a few polyfill that you can use for the moment that will use this API if it's available and fall back using the url hash

Consider this JavaScript library: https://github.com/browserstate/history.js

Use jquery. It can do ajax requests. You cant use window.location because that is made to change the url.

Related

Refreshing a page with cookies in Play

I have a drop-down selection of available languages. Currently, clicking on a language is mapped to a method in controller which updates the Play Session (which is a cookie under the hood) with the selected language and returns index page.
View:
English
Controller:
def setLanguage(language: String): Action[AnyContent] = Action { implicit request =>
val updatedSession = request.session + (("lang", language))
Redirect(routes.Application.index()).withSession(updatedSession)
}
As you can see, I redirect to index page and it's working fine. However, as the language selection is available at all times on my page, it may be clicked from /resource1, /resource2, /resource3 etc. and I would like to refresh that particular view instead of being returned to home page. I cannot simply get request.uri in the controller and refresh whatever it's pointing to because setLanguage() is mapped to its own route, so my request URI is always /language?lang=whatever.
So, how do I know that prior to invoking GET on /language, client was on, say, /items so I can reload items page instead of returning him to home page? Should I send a GET request with resource as a parameter (e.g. ?lang=en&location=items) to know which page to render? Should I make an ajax request and call window.location.reload() on success? Do I even need to go to server or can I simply update the PLAY_SESSION cookie manually from the client?
I'm using Play 2.3.7.
No you cannot update the PLAY_SESSION cookie from the client side, since it is signed by play with the application secret.
So I think the easiest solution would be, as suggested, to send the current resource as parameter and trigger a redirect.
There is an HTTP header called Referer that contains the url from which the request was made. As far as I know it's supported and used by all modern browsers when you navigate from a page to another.
You can simply redirect to that Referer url.
Another solution is to track in a session or a cookie all pages that are accessed by an user, by using some kind of interceptor in Global.scala or a custom Action builder that you use everywhere. Then in case of language change you can simply redirect to the last page that was accessed by the user.

URL handling on browser BACK button

I am making a simple web app that opens a url on entering a query. I am using the bottle framework in Python. The problem I am facing is as follows:
I have two URL handlers, one for / and other for /process. When the user enters a query through a form on /, the form action goes to /process which then processes the query and opens a particular url using window.open(url, "_self"). Now when the user hits the back button in the browser, /process is called again with the same query, which then again loads the same url. Instead of this, I want it to go / when the back button is pressed. How can I do this? Thanks.
EDIT : I did not notice this before but the above undesired behavior is found in Firefox but not in Chrome.
You can use the window.history object to manipulate and replace the history or, instead of using window.open(url, "_self"), replace the location
example:
window.location.replace(url);
Check some documentation and this answer
In Javascript, how do I "clear" the back (history -1)?
Another solution could be to intercept when the user is going to go back. Check this answer to have some examples:
Intercepting call to the back button in my AJAX application: I don't want it to do anything!
Don't redirect using window.open, or any kind of client-side JavaScript.
Have the HTTP response to the request for /process be a 302 Found HTTP status with a Location header.
See also The Post/Redirect/Get Pattern.

store the url, then once stored, to load a different url?

I basically nees a redirect, but the my problem is the first url must be stored otherwise the other page will not display.
how do i get jquery or javascript to store the current (or specified) url, then once stored it must load a different (specified) url?
You can't simply store it in a variable, because when a new URL is loaded, the entire javascript context is new. You can store the current URL in a cookie, though.
If you're trying to pass the URL from one page to the next, the cookie approach will only work if the two pages are on the same domain.
If you have any kind of server-side component in your stack (e.g. PHP) it seems like a more sensible approach would be to store the URL server-side.
Edited to add: You requested sample code for the cookies. Reading and writing cookies in Javascript requires a certain amount of boilerplate code; there are example methods here or you can use a jQuery plugin.
Once you have a simple way to write and read your cookies, you can just do (this syntax uses the jquery plugin)
//assuming "newURL" hold the new url you want to load
$.cookie("currentURL",window.location.href);
window.location = newURL;
Then on the next page you can get the old URL:
var oldURL = $.cookie("currentURL");
To do this with a client side script like JavaScript/jQuery, you'll need AJAX. You send off a request to the server with the URL to store and you can get back the URL to redirect to, if desired. Once the response is received from the server, you redirect to the target URL.
However, note that this can't be done with just JavaScript/jQuery. You need a server-side script as well to handle the request to store the URL. Something like PHP, Perl, etc. You may also need a database or at least a flat text file to store the data.
You may want to consider a completely server-side approach. Use a script on the server to read and store the URL and then route the request to the proper destination. It will be a faster and more seamless experience for the user and less stuff for you to build and maintain.

How to avoid ajax reload when you click the back button

I have a page that used Ajax to generate the a list of result. Then there is a link to click to another detail page. When I'm at the detail page, and click the back button. The list of results page will reload again. Is there anyway to stop the ajax to reload again and cache the result. Also is there anyway to cache the position also.
thank you for your help
A few projects I had bookmarked regarding the AJAX/back button management
https://github.com/browserstate/history.js
https://github.com/tkyk/jquery-history-plugin
Regarding your second question, if your browser supports local DB you may cache the result there. The following project provide a uniform API across browsers.
https://github.com/marcuswestin/store.js
https://github.com/alexmng/sticky
Position can also be stored in the localDB.
You can save state by changing the window.location.hash property. The hash is the only part of the URL that you can change and not force a reload of the URL.
window.location.hash = 'some-id'; will translate into your URL looking like this: index.html#some-id.
You can then get the hash when the page loads and set the UI to the proper state:
if (window.location.hash == 'some-id') {
//setup UI for `some-id` identifier
}
https://developer.mozilla.org/en/DOM/Storage
Store your data with a timestamp of some sort. Check to see if you have stored data and that it's not older than you would like it to be. If it's older, fetch new data. If not use the stored data.
(it's not mozilla specific)
http://caniuse.com/#search=local%20storage
You can use the new HTML5 LocalStorage system to build a cache. Here's a link: http://playground.html5rocks.com/#localstorage

Changing Javascript History

When I load my php page I append some data. For instance MyPage.php?value=something.
As expected, when I go back and forth using the back button, it always loads with that same data appended. I don't want that. I want that after the page loads, I should be able to change the history to store only MyPage.php WITHOUT the appended data.So now when I would use the back button it would load MyPage.php only. How can I do this - javascript, jquery, php , anything???
If there is a way to do that without touching the history object, thats also fine. I'm just assumng it'll take some history tweaking. I'm also OK if it takes tweaking on the client or server side.
As far as I know, it is not possible to tweak the history like that, nor is it a good way to deal with this.
You could use a cookie to determine when a page gets loaded more than twice, or store the data in a session variable instead, and delete it once your processing is done.
I assume the data is appended by using GET method. Using POST will not append text after MyPage.php but still can pass data to the page.
The history is the history. It's a bit of a hack to go changing that (and you will probably have other issues down the road if you do).
It is better to either have NO querystring at all, and use js or server-side logic to determine the action, or to have js or server-side logic to ignore the second request.
If you are fine with tweaking the history then you can probably look in to this.
history.replaceState({}, document.title, "MyPage.php");
This will rewrite the current window.location to "MyPage.php" without page refresh.

Categories

Resources