How to handle URL change by JavaScript - javascript

I know that in modern browsers I can change the URL silently (without page reload) like this:
window.history.pushState(“object or string”, “Title”, “/new-url”);
But I want to be able to detect changes in URL. When user enters the new URL in the address bar how can I handle the event and prevent the page from reloading?
P.S. I know I can use onhashchange but I just don't want to use hashes :)

As stated in Event when window.location.href changes it is not possible without polling. This was 2010. Maybe in the meanwhile there is a solution for HTML5 browsers.
Probably you already know that not using hashchange has drawbacks regarding server-side, crawling, 404-detection, ...
But using hashes has disadvantages as well, especially when it comes to deep links sent by mail (redirects don't transport hashes, typically used by webmail-clients to have clean referers).
I recommend to use a tested library for url-routing and history API. I'm sure you find one either at microjs.com, JSter or JSDB.IO. There are many which do a graceful fallback on disabled browsers like MSIE.
My best bets would be history.js and Crossroads.js (with Hasher).
If you already use a MVC framework like Backbone.js, AngularJS, Ember or the like you'll get what you want for free.
After all I'm not really sure whether any of these libraries are able to supress reloading of the (single-) page when location.href changes. Since your losing most of your state I'd use #hashes. IMHO, Users of Single-Page-Apps shouldn't change the browser location but use navigation options of your App.

Related

onhashchange vs pushState

I am creating an internal dashboard on my site which is only accessible to logged in users and therefore is not indexable / crawlable by search engines. This dashboard is mainly a single-page app. Also, I don't care (at least I don't think I care) about having pretty urls: there is no progressive enhancement - if javascript is disabled, then the dashboard is not functional.
What I need is the ability to navigate using the back / forward button between different states - for instance, various modals that are opened. And very importantly, I need to be able to link externally to the specific state of the dashboard (e.g. modal A was open in this configuration) - e.g. via emails to users containing links to the dashboard.
Given all this, is there any preference to "old school" hash bangs (#!) vs html5 pushState? pushState will require me to use something like history.js for older browser support anyway. And architecturally speaking, if my dashboard is at the following url:
http://example.com/dashboard
won't I have to perform nearly identical operations to resolve to a particular modal state regardless of whether I'm using pushState or onhashchange? In other words:
http://example.com/dashboard#!modalA/state1
or
http://example.com/dashboard/modalA/state1
both of which will require parsing client side (done by a framework) to figure out how to display the current dashboard state. My backend controller would still be mapping to /dashboard/* for any dashboard url since all of the state concern is handled on the client.
Am I missing something? Not that it should matter, but I am using CanJS which supports both hash events and pushState.
Note: my question is not specific to Google's hashbang proposal, but to the general use of the # (onhashchange).
This article does a pretty good job of summing up the potential issues with using hash/hashbang, albeit it's pretty biased against them- often with good reason.
You are in a pretty fortunate position given that:
You don't have to worry about SEO concerns
Your app is internal to your organization
To me this makes your choice pretty clear cut depending on whether or not you can require those within your organization to upgrade their browsers to a version that is HTML5 compatible, if they haven't already. So, if you have that ability, use HTML5 History api. If you don't, use hash. If you want HTML5 pushState with an HTML4 onhashchange fallback, you can do that as well though it'll require some extra work to ensure all your HTML5 links work for HTML4 users.

On the fly website manipulation using

I am trying to work out if I can alter the functionality of a website preferably through vba (access) or any other way that I can centrally manage. What I am trying to achieve is, depending on permissions, I would like users to log onto a website and the website is then changed on the fly to stop the user using normal functions of the website. For example some users have access to a submit button while others do not.
I have seen that you can use VBA to parse websites and auto logon. I'm just not sure if its capable of doing any local scripting like greasemonkey does.
Maybe I am looking at this wrong and can achieve this at the firewall level instead of running website scripts.
Any ideas?
You should not manage website permissions using a client-side technology like JavaScript. Users can easily either just disable JavaScript/VBScript or tamper with the page.
The best approach is to manage permissions by emitting the HTML from a server-side scripting language such as ASP.Net or PHP.
ASP.Net has built-in, generally adequate support for membership, roles and permissions that would meet this need.
http://msdn.microsoft.com/en-us/library/yh26yfzy(v=vs.100).aspx
If that is not an option for whatever reason, and you can accept the risk of someone tampering with the permissions you setup, you can certainly use something like jQuery to hide portions of an HTML document that a user should have no access to. You can accomplish the same thing using JavaScript without jQuery, but I would suggest jQuery because it abstracts away many of the cross-browser issues.
If you do that, hide everything by default and then show selectively based on permissions. That way, the simplest method of just disabling JavaScript will not reveal anything special (though it is still quite easy to hack).

Having an HTML5 MP3 player persist across page loads

So I've been doing a little research on the different methods to achieve having a player (or any element for that matter) persist across page loads like this and it seems like there are two options. Both of which I will be creating my site to harness AJAX loads:
Hash bang - This seems to have a lot of hatred across the web but should work in all browsers as of right now. It also seems to be very easy to implement.
HTML5 History - From what I've read this is the "proper" way to do this, however, it has very limited browser support at this point. For browser that aren't supported full page refreshes will occur (History.js).
So my question is: Is there a third option? Or can someone please weigh in on the above two? It seems like HTML5 History is "better" but if I need the site to work correctly in all browsers then Hash bang is my only option. Is this true?
Use history and onpopstate as the first option, but when that fails, set the hash bangs. Then make sure that your routing can handle both the hash bangs and the pretty onpopstate URLs, so that users can follow either bookmark.
I've used this configuration once myself, and it wasn't a whole lot of JavaScript. It was annoying to get it all right, but it was doable and worth the effort to deliver the best experience in all browsers.
I'd love to hear a second opinion on this if there's a better solution.

How can I use #-URLs in a single-page application?

This article makes a pretty convincing argument that because URLs are long-lived (they get bookmarked and passed around), they should be meaningful, and that using the hash for real routing (determining what data is shown on the page and/or the state of the application) is thus improper. When I try to actually do that in my single-page application, though, I run up against a problem: how do I render my links so that all browsers can use the application? As I see it, there are three options:
all hrefs have a #/ prefix. This works great in HTML4 browsers. In HTML5 browsers, I can add a Sammy route that redirects to the hash-less version, which also works great. There might be a problem with browsers marking links as visited when they're not or not marking them visited when they are. The other problem is that it's... wrong. Anyone who shares a link by right-clicking it and selecting "Copy Link URL" will be sending a working but kludgy URL around.
no hrefs have a #/ prefix. As far as I can tell, HTML4 browsers will have no way of intercepting these link clicks, which means that every one will cause a page refresh. Though the application would probably still function, since I could use Sammy routes to rewrite the hashless versions to hashy ones on page load, the page loads would kill the performance of the single-page application.
I dynamically determine whether to prefix with #/ or not. This means that all of my links have to have dynamic markup and dramatically complicates the application.
The hash value of a URL never caused and entire re-load of page. Not in HTML4 and before that. A hash value has always been an internal link, and therefore it can be used perfectly (take a look at twitter for example). Of course, when you refresh the page, you will reload the page. But that is obvious.
With JavaScript you can actually read this hash value (see also this question/answer: How can you check for a #hash in a URL using JavaScript?) using window.location.hash
Using a more recent browser, you can also detect a hash change, which is useful if users actually change the URL: On - window.location.hash - Change?
But when you, as the website, change the URL you don't need read this, you already know because you just changed it.
This way, using hashes, people can exchange the URLs, and you can actually read which URL they are requesting, and therefore it should work perfectly.

jquery ajax history and bookmarking plugin

There are plugins for handling history and bookmarking like: http://plugins.jquery.com/project/history. Somehow it doesn't look as a complete solution. For example, on one page you might have a filter that consists of several checkboxes, text boxes etc. You would like your page history functionality to update all those controls and to update url when value of some of those controls is changed. With the jquery history plugin, you would have to write all that code (even parsing of the hash value from url). Is there some more complete solution for this problem?
Ben Alman has recently released a fantastic plugin to handle things related to the questions you are asking. It is called jQuery BBQ (for Back Button and Query). It has excellent documentation, full unit tests and is alot more up to date than the antiquated jQuery History plugin. I especially like the onhashchange work that he did. (5 Stars. would do business with again A+++)
Perhaps try this jQuery History plugin: https://github.com/browserstate/history.js
It provides cross browser support, binding to hashes, overloading hashes, all the rest.
There is also a Ajax extension for it, allowing it to easily upgrade your webpage into a proper Ajax application: http://browserstate.github.com/history.js/demo/
This is the solution chosen by such sites as http://wbhomes.com.au/ and http://gatesonline.com.au/stage/public/
Overall it is well documented, supported and feature rich. It's also won a bounty question here How to show Ajax requests in URL?

Categories