Usage of Hash(#) in URL - javascript

I was wondering is there any use of hash other than as an anchor in URL. I read about it here
getting the full url including query string after hash .
What is state information for the client? Please help.

The hash can be used also for single page applications, so instead of using it to navigate to a point in a page you use the hash as a means for navigated from page to page. The advantage of this is that it does not require a page refresh.
There is also a method called hashbanging which is used for single page applications and is used for helping ajax applications more indexible.
There are a few good articles on the subject
https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling
http://danwebb.net/2011/5/28/it-is-about-the-hashbangs
https://developers.google.com/webmasters/ajax-crawling/

Consider one page website, or website built fully on AJAX, without any page reloads.
#hash helps such applications to push state of the application to the client, this helps the application itself to be aware of the state and the client (and browser) to be aware of the state. This will also help the user to bookmark the application in its' current state and use back and forward buttons (browser history).

Related

Mean Stack Application: Page does not rerender on refresh, but returns only JSON

I'm currently designing a MEAN.js web application, and for some reason, whenever I refresh the page on a route or window.reload, it does not rerender the page, but only returns the JSON file found at that current route.
For example, when I'm at localhost:8080/people:
If I click here from the main page, I get
But if I hit refresh or reload the page for whatever reason I get
Does anyone have any idea why this is happening and how to fix it?
Presumably you are using what Angular call's html5Mode routing.
This uses pushState and friends. These are browser features designed to allow you to build a web app which has what appear to be separate pages with unique, real URLs but when you change the page you actually modify the DOM of the current page (to State B) instead of loading a new one from scratch.
The design intention for pushState and friends is that if you request the unique, real URL that maps onto State B then the server will provide the browser with the HTML for State B directly.
This means that:
if you arrive on the site without going to the homepage first, then you
load the content you are trying to load directly (which is faster than loading the homepage and then modifying it with JavaScript).
if you arrive on the site without JavaScript working (which could be for many reasons, then everything still works. See also Progressive Enhancement and Unobtrusive JavaScript.
What you've done wrong is that your URLs are mapping onto your JSON based API instead of server side processes that generate the pages.
You need to write the server side processes. You could consider using the Accept header to allow them to share URLs with the API (so the server returns either JSON or HTML depending on what the client says it accepts).

can local storage store the whole page

so I have seen a lot of people using local storage to store certain parts of a web page but not an entire web page is it possible? , if so how? , if not is there a way to store an entire web pages data so the user can come back to it how they left it?
This can be done if you use javascript to save document.body.innerHTML into the webstorage and you use javascript to load it back from the storage when the page is loaded next time. If the web page is not in the webstorage, you could redirect the user to the web page.
But this depends on the design of your web page and if there is session index etc in the body of the web page.
You should also think of some way to handle versions. You dont want your users only use the cached version of your web page, but it should be updated once you update your web page.
The session storage is ~5mbit, so you cant save very much, especially not pictures.
Since LocalStorage allows you to store about 5MB~ you can store a full webpage there and then just call it into a document.write().
The following code does it:
Storing it:
var HTML = ""; //html of the page goes here
localStorage.setItem("content", HTML);
Retrieving it:
document.write(localStorage['content']);
Although this is possible it is common practice you only save settings and load them up into the right elements rather than the entire web page.
This is not really answering your question, but, if you are only curious how this can be done and don't need to have wide browser support, I suggest you look into Service Workers, as making websites offline is something that they solve very well.
One of their many capabilities is that they can act as a proxy for any request your website makes, and respond with locally saved data, instead of going to the server.
This allows you to write your application code exactly the same way as you would normally, with the exception of initializing the ServiceWorker (this is done only once)
https://developers.google.com/web/fundamentals/getting-started/primers/service-workers
https://jakearchibald.github.io/isserviceworkerready/
Local storage it's actually just an endpoint: has an IP address and can be accessed from the web.
First of all, you need to make sure that you're DNS service points on your Index page.
For example, if your Local-storage's ip is 10.10.10.10 and the files on that local-storage is organized like:
contants:
pages:
index.html
page2.html
images:
welcome.png
So you can point your DNS like:
10.10.10.10/index -> /contants/pages/index.html
In most of the web frameworks (web framework it's a library that provide built in tools that enable you to build your web site with more functionality and more easily) their is a built in module called 'route' that provide more functionality like this.
In that way, from you index.html file you can import the entire web site, for example:
and in your routes you define for example:
For all the files with the .html extension, route to -> 10.10.10.10/contants/pages/
For all the files with the .png/.jpg extension, route to -> 10.10.10.10/contants/images/
Local storage is usually for storing key and value pairs, storing a whole page will be a ridiculous idea. Try instead a Ajax call which Returns an partial view. Use that for the purpose of manipulation in DOM

Back button handling in Single Page Apps?

A similar question here has been noted!
I've got an SPA based exclusively on the DHTMLX toolkit (fabulous stuff incidentally). One serious UX problem is with back button handling: there is none.
Their forum recommended 'any js routing library to handle state of the app in the url hash and restore it back'.
I am confused by this as the SPA has only the simplest HTML, is exclusively Javascript and does most communicating via WebSockets ... does this mean I have to store state on each button click/keypress?
So, ...
Does the panel have any recommendations on best practices?
Is there an existing library that will do this?
If said library is light on examples, can anyone provide a basic how-to?
Many thanks
Dhtmlx is a great framework for building SPAs. Like all SPAs, the back button will simply take the user right out of app. Also the user cannot bookmark anything.
So what you want to do is use javascript's pushState() which will allow you to control the url.
For example, suppose you show a search screen to go to a record. The user enters the search criteria and presses search. You bring in the results via ajax and update a grid. Then the user selects the row and you go to a detail page (typical search functionality here).
At this point, you would want to use pushState() to change the url to something like:
http:/me.com/search/23432
This will allow the user to bookmark the page. Then when the user leaves the detail page, use pushState() and set the url to http:/me.com/search
So you have complete control over the url.
The next thing you need to learn is popState(). This function is called when the url changes. So suppose the user pushes the bookmark to go to "23432". popState() will be called and you'll react accordingly.
That's basically it in a nutshell: pushState() and popState().
Some older browsers do not react to pushState/popState. There are libraries floating around to handle older browsers using url hashing. I am not too familiar with them as I am only supporting html5 browsers.

Angular app spanning subdomains

So I am building an angular app that allows people to create books and share them (digital books mind you) with a subdomain link.
So something like mycoolbook.theappsite.com would be a sharable link.
I (perhaps stupidly) built the routes so that editing books would be at the url "mycoolbook.theappsite.com/settings".
This being an angular page I am having to do hard redirects between those pages and so miss out on much of the SPA-y goodness. Is there a way to keep the app instance running between those pages?
If not I might move all the admin pages back behind the url like "theappsite.com/book/mycoolbook/settings" instead.
Is this at all possible?
I've already done all the hard work of getting sessions and ajax request working across the domains, it's just the state linking that becomes bothersome.
Short answer is no and have the URL change to reflect it. You cannot change book.domain.com -> domain.com because angular manipulates the URL, but only the fragment section of the URL in hash mode and just the path, search string, hash in HTML5 Mode. Not the other parts of the URL. If your application is using HTML5 mode your server must be able to map URLs properly so they return the correct page (ie index.html) as you change the URL. That would mean both DNS locations would have to send back the same page.
Now you can send AJAX requests between the two domains provided you understand how to deal with cross domain issues (JSONP, CORS, etc).

Custom back button based on history

In my one-page web app, I would like to have a back button on some of the pages that takes the user back to a specific point in their browser history: not necessarily the previous page.
Note that I am not talking about the browser's back button, which should work as usual.
Use Case
For an example, consider the gmail web app. There is a folder view, potentially with search filters or other parameters, and then a message view that shows a single message. In the messages view, there is a back button that does not take you to the previous page: even if you have clicked around reading several messages, the back button will take you back to the folder view from which you originally came before clicking on any of the messages.
In the case of gmail, this is achieved by simply encoding the previous state at the end of the URL. E.g., if you got to this message by searching, it will be:
#search/stuff/<MESSAGE_ID>
From this, the app knows that the back button should point to the page with:
#search/stuff
In my application, however, there is too much state to encode it all in the URL. Rather than two views (folder + message), there are three views, let's call them A, B, and details, with both A and B having a wide array of possible filters and options encoded in the URL that I would like to preserve when e.g. returning from B to A or from details to B. Encoding all the parameters for A, B and details in the URL of the details page would make the URL extremely unwieldy.
Implementation
I thought this could be easily achieved using the html5 history API. However, as far as I can see the history API does not provide support for reading the URLs in the history: you can only blindly go back or forward.
history.js provides access to past states, as discussed in a related question:
History API: Javascript Pushstate, get previous URL
However, I am using angularjs which does not work well with history.js, because it talks directly to the history api instead of going through history.js, so the states from transitions caused by the angular $location service do not show up in history.js' History object.
It seems that what I would need to do one of the following:
get history.js to work well with angular
re-implement a subset of history.js' functionality in my own code
I also considered using document.referrer to peek at the previous value in history, but that does not work as it does not get set when navigating within a one-page app.
Answering my own question, I chose to go for the simpler solution suggested by #MaxArt in his comment.
Generate a random ID for a page
Since I use angularjs, I do this $on('$routeChangeSuccess') or $on('$routeUpdate')
without angularjs, I suppose I would do this onpopstate
Store a mapping from this random ID to all the URL information that I need (in my case, search and path) in sessionStorage
Include a search parameter from=the ID of the current page in outgoing links that go forward in the conceptual hierarchy of my app
When the custom back button is clicked, look up the state I come from in sessionStorage using the from seach parameter
if found, go back to that URL
if not found (user navigated to this page directlry), go back to the default URL for the previous view in the app's hierarchy
Rationale for taking this approach over the more general approach of building a history of past URLs:
As mentioned, the pushState API does NOT provide access to past URLs
Integrating History.js, which does provide that information, into angularjs does not seem trivial
angularjs uses the history API internally: it would need to be changed to instead use History
Implementing custom code to record the URL history in sessionStorage is also not trivial. The main problem is that, lacking integration with the browser's history, there does not seem to be a general way to know if a visited page is new or it was reached by going back one or more steps in the browser history. I'd be happy to be corrected on this if someone can suggest a solution (1)
Using History.js or any equivalent solution that wraps all history.pushState with additional code, requires pretty much all links on the page to be wrapped in History.pushState, otherwise URL changes do not show up in the History.
(1) How do I retrieve if the popstate event comes from back or forward actions with the HTML5 pushstate?
I've never worked with angular.js, but presumably window.history.pushState is what you're looking for if you want something guaranteed to work. Have a read-over of http://spoiledmilk.com/blog/html5-changing-the-browser-url-without-refreshing-page/ for the detailed information on what this baby can do.

Categories

Resources