Enabling back/fwd key events for an Ajax Application - javascript

I have an application which works heavily on AJAX. However I want to have navigation functionalities in it. To spoof the url, I am changing the location.hash, to generate URL. But if I use back/fwd, only the url changes, but page wont reload. How can I override the hstory.back to reload the page.

I don't know of any other way than continuous polling to implement this behaviour. An implementation might look like this:
var lastHash = '';
function pollHash() {
if(lastHash !== location.hash) {
lastHash = location.hash;
// hash has changed, so do stuff:
alert(lastHash);
}
}
setInterval(pollHash, 100);

You can't exactly capture the back event, but most of these problems have been solved - and a good thing too, it's a hard problem.
Take a look at really simple history (aka RSH) and either implement it or work through it to see how it works.

The answer for this question will be more or less the same as my answers for these questions:
How to show Ajax requests in URL?
How does Gmail handle back/forward in rich JavaScript?
In summary, two projects that you'll probably want to look at which explain the whole hashchange process and using it with ajax are:
jQuery History (using hashes to manage your pages state and bind to changes to update your page).
jQuery Ajaxy (ajax extension for jQuery History, to allow for complete ajax websites while being completely unobtrusive and gracefully degradable).

The balupton answers are really great.
But you also have another jQuery Plugin to handle your ajax requests, it is address.

Related

Dynamic web page with no reloading

I've just recently discovered slack.com and I fell in love with the way they handle their interface. If you've never used it before it's quite easy:
There is a side navbar and an main container on the right. Everytime you click an item in the side navbar it's content is loaded in the container. The focused item changes, the container's content changes, but the page doesn't reload.
If the data changes in the meantime it is magically updated.
What would it take to achieve something like that?
URL changing, page not reloading
Content always up to date
I've been looking at meteorjs in the past few days but the url part is never mentionned.
Yes. Slack is awesome. We (My team) use it everyday. I use it so regularly, at some point I don't check email but I check slack.
So, up to your question.
URL changing, page not reloading
It can be easily done by javascript [ Tl;dr ]
Code:
window.history.pushState("object or string", "Title", "/new-url");
Content always up to date
Well this can be done in two way,
i. via Ajax and Javascript
ii. via socket
i. via Ajax and Javascript:
in javascript you can make setTimeout function to fire ajax request in some duration. via Ajax it will get newest message from backend and it will be shown.
ii. via socket:
in socket, in your case if you use node.js there is a very popular library named socket.io which will get and update message in real time.
Good luck!
You need Ajax. You can use it in conjunction with a script, probably PHP that checks the state of the databse over a timer interval (a "heartbeat") and if anything has changed you load in the new data. I'd recommend having a specific column for a datetimestamp to compare with to make the smallest possible load on your database from this as a lot of users being on the page at the same time will make a lot of requests.
For the "url changing feature but no reload", I think #Kavan Pancholi answered your question. Another way to achieve that is by using the yield templates feature of iron-router.
You are using meteor, it means that you can do it without too much trouble (forget about Ajax & Sockets).
I don't know Slack (but I'll definitely have a look at it) but from what I understand, all data is preloaded/lazy loaded and they only change the displayed elements. In other terms, you keep ready and loaded all your client subscriptions or you bring them up when your yield template is loaded.
I will have a look at Slack and edit this if I realize I did not understood correctly what you are aiming for.
Edit Ok I tried it. You need to use yield templates with iron-router and they also added some transitions effect you can achieve with _uihooks + a loading template
On top of that, if you use a framework like angular, you'll notice urls like this:
http://localhost:3000/#/chat/room
You've probably seen similar with wikipedia in having urls like this:
https://en.wikipedia.org/wiki/Cat#Cats_and_humans
That little # won't reload the page on the url, so you can use that to make a url routing action without changing the page. You can access it with window.location.hash. So on the wikipedia article, you'd get
> window.location.hash
#Cats_and_humans
Combine that with ajax and event listeners and you can do something similar.
// using jquery
// set a callback when the hash changes
$(window).on('hashchange', function (e) {
e.preventDefault();
var hash = window.location.hash;
// get your container where you want to add data and clear it out
var $container = $('#container');
$container.html('<ul></ul>');
if (hash === '#/movies') {
// request json from an endpoint, and with the data, append it to the dom
$.getJSON('/api/movies', function (data) {
data.each(function (el) {
$container.append('<li>' + el.name + '</li>');
});
});
}
});

Javascript reload to load a new instance and not reload the page

I am using window.location.reload in a jQuery dialog on close. The issue is that if users posted to the page earlier, it will give them a dialog to reload the post data. Is there a way to load the page without "reloading", or "refreshing".
Something similiar to PHP's header("Location");
I need it to load the same url, just not reload it.
I understand that I can use window.location = window.location, but this does not work.
How about window.location.href = document.URL;
In addition to the direct answers, looking at this issue from a broader scope might help.
The user is being prompted to reload post data because they came to that page via a POST method - if you were to employ the PRG pattern, you'd avoid the post data prompt, and reap the various other benefits it provides. That said, it is a bit more work :)

History.pushState and page refresh

I started looking at HTML5 new history API
However, I have one question. How can one handles the page refresh?
For example a user clicks a link, which is handled by a js function, which
asynchronously loads the content of the page
changes the URL with history.pushState()
The the user refreshes the page, but the URL of course does not exist on the server
How do you handle situations like this? With the hash solution there was no issue there
Thanks
This does require the server-side support. The ideal use of .pushState is to allow URLs from JavaScript applications to be handled intelligently by the server.
This could be either by re-serving the same JavaScript application, and letting it inspect window.location, or by rendering the content at that URL on the server as you would for a normal web application. The specifics obviously vary depending on what you're doing.
You need to perform server side redirection for copy and pasted fake URLs
It all depends on what server side technology you're using. There is no JavaScript way but writing a crazy function in your 404 page that redirect user based on incoming URL that is not a good solution.
The the user refreshes the page, but the URL of course does not exist
on the server
What do you mean by this? I have a feeling your assumption is wrong.
Actually yes, the point is it is the developer who should provide (serverside or clientside) implementation of url-to-pagestate correspondence.
If, once again, I've get the question right.
If you are using ASP.NET MVC on your server, you can add the following to your RegisterRoutes function:
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
This will send all requests to Index action of your HomeController and your UI will handle the actual route.
For people looking for a JS-only solution, use the popstate event on window. Please see MDN - popstate for full details, but essentially this event is passed the state object you gave to pushState or replaceState. You can access this object like event.state and use it's data to determine what to do, ie show an AJAX portion of a page.
I'm not sure if this was unavailable in 2011 but this is available in all modern browsers (IE10+), now.

Could a page display diferrent content if the URL hash changes?

How could a page display different content based on the URL hash?
I'm not talking about the browser scrolling down to display the anchored section, but something like JavaScript reacting to that hash and loading different content via AJAX.
Is this common or even probable?
Oh yes - it's becoming a common pattern to handle page-state-to-URL persistence when content is AJAX driven.
Javascript can access this value via window.location.hash. Once that's done, you can perform any actions based on the value of that hash
Show/hide nodes
Makes other AJAX calls
Change page titles or colors
Swap images
etc
Really, any DHTML effect.
This is occasionally done. Youtube uses hashes to link to specific timestamps within a video.
EDIT: I had assumed that you might have an issue where if the user goes up and manually edits the hash in the address bar, the page doesn't reload and even javascript will not know that it changed. I was wrong. I tried it on Youtube it works.
I just built a system to do this a few weeks ago
depeding on the browser you need to detect the hash, heres how to do that
// test all possible places hash could be on different browsers
if(window.location.hash){
hash = window.location.hash;
} else if (document.location.hash){
hash = document.location.hash;
} else if (location.hash){
hash = location.hash;
}
// some browsers start the hash with #, remove it for consistency
if(hash.substring(0,1) == '#'){
hash = hash.substring(1,hash.length);
}
Then handle the value of the hash variable to trigger page changes as you please.
for example:
http://www.example.com#pageA
if(hash = 'pageA'){
document.getElementById('mainContentDiv').innerHTML = '<p> content for the page displayed when the hash sais pageA</p>';
}
Sammy is a javascript library that does just this.
As JavaScript has access to the URL-string it could of course act differently on the contents of the url.
I've occassionally seen something like this but I don't think that this is a good way to react unless in very specific uses.
One of the uses I remember was TiddlyWiki using the after-portion of the hash to set preferences for the page rendering and such.
It is fairly common among AJAX-heavy applications (think Gmail) to be able to have all the AJAXy stuff while still making it possible for you to bookmark a particular page or link someone to a particular page. If they didn't do this, it would be considered bad for usability. It is fairly easy to get the URL hash by doing window.location.hash - so you can then have a switch-like statement on page load to execute a particular set of Javascript functions if a hash is present.
Some jQuery plugins that achieve this functionality: history/remote, history.
The answer for this question will be more or less the same as my answers for these questions:
How to show Ajax requests in URL?
How does Gmail handle back/forward in rich JavaScript?
In summary, two projects that you'll probably want to look at which explain the whole hashchange process and using it with ajax are:
jQuery History (using hashes to manage your pages state and bind to changes to update your page).
jQuery Ajaxy (ajax extension for jQuery History, to allow for complete ajax websites while being completely unobtrusive and gracefully degradable).

How to monitor the changes in the url (Fragment identifier - the anchor portion of a URL )

I'm making a website that tend to handle all the request in one page (Ajax).
so i thought that I could trap every user's click on a link and check IF it's on my website i do something on JavaScript like an ajax request for example, ELSE it would open the link like usual!
doing a watch on window.location did not work!
and moreover I don't know if there is anyway to get the url part that is after the # sign.
Note: both GMail, and Facebook does that I guess!, they use something like this:
http://mail.google.com/mail/#inbox
http://www.facebook.com/home.php#/inbox/?ref=mb
Kindly Consider: that I love to use jQuery in my projects, so any solution using it is preferred.
Any ideas?
Here is another good read: Restoring Conventional Browser Navigation to AJAX Applications
Excerpt from the article:
Many developers have adopted AJAX as a
way to develop rich web applications
that are almost as interactive and
responsive as desktop applications.
AJAX works by dividing the web UI into
different segments. A user can perform
an operation on one segment and then
start working on other segments
without waiting for the first
operation to finish.
But AJAX has a major disadvantage; it
breaks standard browser behavior, such
as Back, Forward, and bookmarking
support. Rather than forcing users to
adapt to AJAX's shortcomings,
developers should make their AJAX
applications comply with the
traditional web interaction
style,.......
The fragment part of the URL is used to enable navigation history (back and forward buttons) on AJAX-enabled websites. If you want to "trap" clicks on links, since you're using jQuery anyway, you could just do that:
$('a').click(function()
{
var item = $(this);
var url = item.attr('href');
// your logic here
});
If you use fragments (window.location.hash) in constellation with AJAX, note that IE6 submits the fragment part of the url in AJAX requests which can lead to very hard-to-debug bugs, so be aware of that.
There's a hashchange event dispatched on the window for most recent browsers.
Simple:
if(window.location.hash) {
// Fragment exists
} else {
// Fragment doesn't exist
}
Link:
How can you check for a #hash in a URL using JavaScript?
See #Pekka 's link to How can you check for a #hash in a URL using JavaScript? to look at the hash. Just put that function in the callback to window.setInterval()

Categories

Resources