Hashchange not firing when user clicks on same link - javascript

I'm creating an HTML and Javascript client for running in browser which talks to REST API. I'm using RouteMap to set my URLs. So I've kept a convention something like this
http://mysite.com/#/{ResourceName}/[edit|view|list]/[Id]/
I've set just one route and I'm grabbing these parameters in the function bounded to hashchange. Most of the things work fine. Just two issues and I'm stuck because of them.
If the user clicks on the same link twice, hashchange event doesn't fire. Yes, hash has not changed so obviously it won't fire. But there should be something which can be done and I'm missing that.
If I change something in the UI (like bring up new divs and hide some) for which I don't want to change the hash link, I loose that history and can't go back by clicking the back button properly.
Any help will be grateful.

For #1, you probably want to attach a handler to the link click event. That way you can tell if the link is being clicked. When I use onhashchange, I always attach something to the click event to assist polyfills for onhashchange, so at least I can tell when it's failing.
For #2, I want to point out that having automatic stuff change the user's history is problematic. You could fill someone's history with minute, meaningless hash changes. I recommend only changing the history when the user actually interacts. Short of that, HTML5 does offer pushState and popState. Reference

Related

Focus blur on client routing ideal for SPAs?

I have a single page application. There is a page with products and on the bottom a link to go to the next page. Upon clicking this "next" link the list of products in the DOM is replaced. While the link clicked has stayed the same and maintains focus from the click. Is it better for me to do something like document.activeElement.blur() is that case? Or should I just leave focus on that as is?
I'm unsure what best practice is as with normal server routed pages the focus would be reset with the page load. But I haven't seen any information indicating manually resetting focus on client routing would be the best experience from an accessibility point of view.
Never ever use blur. It's just bad, random and possibly frustrating.
IN a native application, you should always exactly know where the focus is, and the focus should always be at a precise place; otherwise keyboard accessibility is broken.
If you consider your web application as being a true application, you should observe the same rigour.
So, never use blur, since you don't know at all where the focus is going to move afterwards. If you are going to remove something from the DOM that currently has focus, you should first place it in another place that make sense.
IN your case: clicking on a link, you have two reasonable options:
Leave the focus on the link (reasonable as long as you don't move, hide or remove it from the DOM)
Move the focus at the beginning of the new content that just appeared / has just been replaced
You may ask users of your application which solution they think is the best, or deduce the answer by observing them during a test session.
Let's summarize quickly: whether you are making an old-style website with different pages, and you don't have to matter much about focus, or you are making a real application and in that case you should be as rigourous as if you were developing a native app.
Terribly simple.

Persistent page action icon

I want to display a notification for the user that will remain constantly visible in the form of a page action until the user does something. I am using this code right now:
chrome.tabs.getSelected(null, function (tab) {
chrome.pageAction.show(tab.id);
});
But that only creates a page action icon on the active tab when the extension is loaded. Instead, I want the icon to show all the time no matter what page or tab the user is on. It also needs to go away when the user does what is necessary to deal with the notification.
I was thinking of two ideas. The first was looping through and adding a page action to every tab, then hooking the new tab and navigation events and adding it to each of those. My second idea was hooking the active tab change event and adding it to the active tab then removing it from the former tab when changing tabs next.
But I thought that there's still probably a better way I didn't think of or didn't know about. So what's the best way to accomplish this?
You need to hook into the onActivated event if you want to get notified of tab changes.
However, that would not be enough, since the page action will reset on navigation. So you'll need to hook into almost every tabs API event to ensure your logic. Also, think of the cleanup required afterwards.
That really does seem like a poor job for a page action. There is also an important consideration that this UI element is not associated, by a typical user, with something that needs attention. Have you considered using notifications instead?
You could use chrome.notifications Rich Notifications together with the priority trick, or just web notifications. In either case it'll be something displayed to the user in a way that is appropriate for "something needs your attention". You can then hook into its onclick event.
If you do want a button, browserAction is totally appropriate. You can dynamically change picture, add a text badge to the icon to attract attention, or just plain disable the button (not hide, but grey out) when there's nothing to do.
According to the documentation, page actions are supposed to be used only for single pages. If you want something to show up on all pages, you should use a browserAction.
Alternatively you can try and set "<all_urls>" in the permissions, but I haven't tested if it actually works.

JavaScript Historic back/forward

I'm building a little CoffeeScript application with 10 buttons and a container (simple). When the user press on one of the button : the container change.
The buttons look like a navbar and instead of using links (that will reload the entire page), I used javascript (Coffeescript, jquery or whatever) to change the content of the page (with some Ajax query to load data).
The problem is that the back and forward button of the browser can't work with that solution... and I need to find a solution for that. Routing maybe ?
I really like the way Asana.com resolved this issue: actually the address change but the content seems not to be entirely reloaded.
What do you suggest ? Thanks for the help
Hashes. The simplest solution is to define an URL hash every time the user clicks on a button. For example:
location.href = "#" + button.id;
With that, you create a history entry, and the user can press back or forward in the browser.
But how can you check when this happens? There's the hashchange event:
window.onhashchange = function() {
var state = location.hash.substring(1); // chomps the initial #
...
};
Basing your code on the state variable, you can trigger your AJAX calls from there.
By the way, you can change your code altogether, using links instead of buttons with an hash as the href property, which does not reload the page, but creates an history entry and fires the hashchange event.
The hashchange event is supported by every modern browser (that support history.pushState too, a more flexible and powerful way to control your history) and IE8-9.

Is there an event for the browser's back button being pressed?

I am supporting an e-commerce app, which pretty much makes and submits orders.
A user found that if they submit their order, and press back really quickly, they can cause an error condition.
I want to prevent this. When the user clicks submit, I want to bind some kind of event to the browser's back button that instead will redirect them to the Index page. However, after about two hours of Googling (including a few StackOverflow topics), I have not found any clear way of influencing the behavior of the back button.
I briefly attempted to use history.pushState(), but as the HTML 5 documentation mentions, that will not cause a redirect; it merely alters the displayed URL/state.
Similarly, the history.onpopstate event appears unhelpful, because it occurs whenever a state is removed from the history listing; I'm looking for an event that occurs whenever the history listing is traversed backwards.
Question: Does an event for the browser's back button, or at least a way to prevent this particular stupid user trick exist?
You can't listen to the browser back button because it's outside of your reach (it's not part of the DOM).
What you can do is fix the previous page so that it detects if you've used the back button.
Without more information I can't give you any tips on how to achieve that.
Also, an error condition is not necessarily a bad thing. Just make sure it's clear what is happening: the error message should make sense.
Wrong answer...
Instead listen to window.onBeforeUnload and ask the user if he knows what he is doing. Return false if not. This is usually done via a confirm dialogue

In Javascript, preferably JQuery, how do I add something to the URL when the user clicks "back" button in the browser?

When the browser clicks "back" button, I want to append "&page=3" to the URL.
How do I bind it, and then do this?
Edit: I want this very simple.
BIND the event{
window.location(that-url + "&page=3")
}
Can it be done that simply?
It sounds like you're trying to create a history plugin.
Have you tried using using the mikage history plugin?
I wouldn't recommend changing the URL when they navigate away from the current page (which is what the back button does), because you immediately erase the forward history (thus breaking the forward button). When trying to handle the back button with pagination and javascript/ajax it is more typical to use the browser hash to pass parameters. The JavaScript namespace doesn't get cleared when the forward and backward buttons are used and the hash is updated according to what navigation was used. These history plugins have a couple of methods to detect when navigation is used (as the doc load event doesn't fire).
So beware, writing a history plugin isn't straightforward because of the way browsers fail to consistently handle hash property of the location object (part of the window object). You will definitely want to look at what others have done.
We use the window.location.hash to handle the history in our app.
I guess it works well in single page apps and is very simple.
For multiple pages app, I don't think it's a good idea to try to control and change the natural page history of the browser.
When the user clicks "back" or "next", the hash key gets the previous or next value.
Because of IE7 you need to use a polling technique (but it is ok in all browsers), with a setInterval(...) and a fast function that checks for instance every 300ms if the hash has changed.
Then, if a change occurs, act accordingly.
ie: call the server and refresh some areas in the page.
It works very well, and does not kill at all the responsiveness of the application.

Categories

Resources