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

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).

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>');
});
});
}
});

Can I change the URL string in the address bar using javascript

I've a link on my webpage, say 'about'. Clicking on it loads a particular div without refreshing the whole page using jquery .load(). This does not change the URL string in the browser address bar.
The same page can be accessed by going to www.mydomain.com/?page=about.
So what I want to do is, when the user clicks on the 'about' link, the pages will be loaded as it is (using jquery), but I want to change the URL string in the browser address bar also so that someone can actually copy or bookmark the exact page.
Is it possible to do so??
You have two possibilites to tackle this problem:
In newer browsers you can make use of the HTML5 history API, which lets change part of the URL, also the query string (and path afaik).
In browsers which don't support this, you can only change the fragment identifier # without reloading the page (via the location object). That means you have to change the URL to e.g.
www.mydomain.com/#!page=about
#! is a convention from Google to make Ajax sites crawlable. As the fragment identifier is not sent to the server, you have to detect it with JavaScript and load the corresponding data from the server.
There are jQuery plugins that help you to handler this.
I would look for a good plugin makes use of the history API if available and falls back to the hash based solution.
As written in my comment, you can also find more information here:
How to change browser address bar without reloading page, especially #ThiefMaster's answer.
Yes, I've done it by doing
location.hash = 'foo';
There's other attributes of location you can change, not sure what it's called for '?', probably query-string, get, or soemthing like that.

Can JavaScript survive a full HTTP Request Roundtrip?

Is it possible to have JavaScript (specifically, JavaScript variables and their content) survive full HTTP requests? I'd like to 'cache' / persist information client-side across page changes, without having to use hidden form fields or anything HTML related at all.
Is this possible?
Edit: Let me add a use case for what I mean.
Let's say I have a JavaScript array
called arrayOfPersons which I
loaded as part of page /HomePage,
and now it contains 1,000 objects
client-side.
Now the user switches the page and
loads an entirely new page /MyAccount into the
browser
My Goal: Still have the arrayOfPersons that I loaded on page /HomePage available after the user requested the entirely new page /MyAccount.
Hope that clarifies what I mean. Thank you!
Just to add to Nick's answer, different browsers support the idea of persistent storage in one form or another. There have been a bunch of efforts to normalize these for all browsers over the last year.
Here's one library that wraps around HTML 5's DOM Storage, Microsoft's UserData, Session Cookies and window.name (using JSON serialization as window.name can only store strings).
Here's another that focuses on window.name only (which actually works in Opera 9+, IE6+, Firefox 1.5+, Safari [3 I think).
Here's a jQuery plugin that uses a .swf (flash) file to offer the most cross-browser support (although it does support native solutions if you configure it to do so). I can't vouch for it but it should be mentioned for this jQuery-lovin' community.
Yes it is possible. Its a bit of a hack i used to maintain the page state(in client side) throughout the entire session.
Have a base page (like master), that never refreshes through out the session and it only got the iframe within it. And all your application pages will be loaded in to that frame..
Store your state info into that master page as JS objects. And you can access the master page (parent) javacript objects from your child page in a iframe. And it ll be maintained through the session in client side.
This is the simplest way. And it works pretty neat.
Found a useful one
JSOC: JavaScript Object Cache
The JSOC framework is a a pluggable,
extensible, open source client-side
caching framework for JavaScript.
JSOC offers Web developers a
straightforward way to perform common
caching techniques (add, replace,
remove, flush, etc.) inside any
JavaScript-enabled browser.
Since JSOC is a standalone JavaScript
module, incorporating JSOC into a Web
development project is a matter of
including a script reference, and
working with common caching methods.
Low-level methods are contained in the
JSOC JavaScript module so that
developers can focus on the Web
development task at hand.
Newer browsers support DOM storage which let you store arbitrary data that can persist between pages. You can also use a hidden Flash app to remember things. There are libraries like Dojo Storage which handle the detection for you, so you just save your data and it will use whatever is available.
It won't automatically save all your Javascript variables for the next page - you'll need to add an onunload handler to store what you want when the user leaves the page.
A frameset would give you a place to persist your javascript, but full page load... I think not.
Cookies might also be useful for "persisting" data, but this isn't what you asked.
if i understand you correctly, all you need is to add your own caching functions into onSubmit of all forms and onClick of all links, smth like:
var cachedpages;
$("A").onclick(function(){
url = $(this).attr('href'); // maybe hash?
if (cachedpages[url]) {
// replacing all html
} else {
$.get(url, function(data){
cachedpages[url] = data;
// replacing all html
});
}
return false;
});
One possibility is to use a frameset and keep the objects there, another to serialize them and persist the data via either of
window.name
document.cookie
location.search
document.cookie is the canonical way to store data between invocations of pages in the same domain and provides mechanisms to control access and lifetime.
If you use window.name, the data persists over the lifetime of the browser instance.
Using window.location is more tricky and you have to explicitly modify the links to send along the data (which can be easily done using event delegation).

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()

Enabling back/fwd key events for an Ajax Application

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.

Categories

Resources