i have followed the samples and currently using event aggregator router for my application in backbone.
so basically i might not use anchor element at all instead i have any element on click event triggering router event.
I still feel that i might be missing something what is the downside of this way of navigating versus directly putting in link via template compilation.
I can think of a couple benefits of using a normal anchor tag with a hash route over having a click event trigger a routing change:
It will make your site easier for search engines to index, thus improving SEO.
It will allow users the ability to easily right or cmd click and open your page in a new tab/window.
Related
I am learning Angular JS ui-router and I was wondering How ui-router manages to change url in navigation bar without reloading entire page?.
I have tried reading this blog and some stackoverflow questions, but couldn't find any proper explaination. Can some one explain properly?
Thanks in advance !
It's based on a simple fact that we can use hyperlinks(<a> tags) to jump to certain sections in a document and bring focus to that section. But if your href attribute points to IDs that do not exist in your page, then the browser will not do anything but change the hash part in the URL.
In modern browsers, everytime, the hash part changes in the URL, a hashchange event will be fired. ui-router or any router can actually listen for this event, get the hash part and use the config to update the view section accordingly.
This works well as long as you trigger a state change by clicking on some link but there are cases where you change the state using methods like $state.go() or $location.path(). In this case, we need to resort to HTML5's History API. There's a pushState method that allows us to change the URL in the address bar without causing the browser to load that resource.
I'm making a game using JavaScript, currently I'm using window.location = "somepage.html" to perform navigation but I'm not sure if that is the correct way to do it. As I said in the title I've choosed Blank App Template so I do not have any navigator.js or something like.
Can you guys tell me the best way to do it?
Although you can use window.location to perform navigation, I'm sure you've already noticed a few of the downsides:
The transition between pages goes through a black screen, which is an artifact of how the underlying HTML rendering engine works.
You lose your script context between pages, e.g. you don't have any shared variables or namespaces, unless you use HTML5 session storage (or WinRT app data).
It's hard to wire up back buttons, e.g. you have to make sure each destination page knows what page navigated to it, and then maintain a back stack in session storage.
It's for these reasons that WinJS + navigator.js created a way to do "pages" via DOM replacement, which is the same strategy used by "single page web apps." That is, you have a div in default.html within which you load an unload DOM fragments to give the appearance of page navigation, while you don't actually ever leave the original script context of default.html. As a result, all of your in-memory variables persist across all page navigations.
The mechanics work like this: WinJS.Navigation provides an API to manage navigation and a backstack. By itself, however, all it really does is manage a backstack array and fire navigation-related events. To do the DOM replacement, something has to be listening to those events.
Those listeners are what navigator.js implements, so that's a piece of code that you can pull into any project for this purpose. Navigator.js also implements a custom control called the PageControlNavigator (usually Application.PageControlNavigator) is what implements the listeners.
That leave the mechanics of how you define your "pages." This is what the WinJS.UI.Pages API is for, and navigator.js assumes that you've defined your pages in this way. (Technically speaking, you can define your own page mechanisms for this, perhaps using the low-level WinJS.UI.Fragments API or even implementing your own from scratch. But WinJS.UI.Pages came about because everyone who approached this problem basically came up with the same solution, so the WinJS team provided one implementation that everyone can use.)
Put together then:
You define each page as an instance of WinJS.UI.Pages.PageControl, where each page is identified by its HTML file (which can load its own JS and CSS files). The JS file contains implementations of a page's methods like ready, in which you can do initialization work. You can then build out any other object structure you want.
In default.html, define a single div for the "host container" for the page rendering. This is an instance of the PageControlNavigator class that's defined in navigator.js. In its data-win-options you specify "{home: }" for the initial page that's loaded.
Whenever you want to switch to another page, call WinJS.Navigation.navigate with the identifier for the target page (namely the path to its .html file). In response, it will fire some navigating events.
In response, the PageControlNavigator's handlers for those events will load the target page's HTML into the DOM, within its div in default.html. It will then unload the previous page's DOM. When all of this gets rendered, you see a page transition--and a smooth one because we can animate the content in and out rather than go through a black screen.
In this process, the previous page control's unload method is called, and the init/load/processed/ready methods of the new page control are called.
It's not too hard to convert a blank app template into a nav template project--move your default.html/.css/.js content into a page control structure, add navigator.js to default.html (and your project), and put a PageControlNavigator into default.html. I suggest that you create a project from the nav app template for reference. Given the explanation above, you should be able to understand the structure.
For more details, refer to Chapter 3 of my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition, where I talk about app anatomy and page navigation with plenty of code examples.
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.
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
I'm currently struggling with a good navigation on a website using Ajax calls and unobstrusive JS. I'm catching the click event on links, load the content, attach it to a div and then return false. This works quite well and also allows Google to crawl the site with speaky URLs.
But I didn't know how to deal with the browser back button. I found this solution to catch the event when the user clicks on the back button:
http://www.bajb.net/2010/02/browser-back-button-detection/
It works quite well. But I also want the back button to work normally when the user found the website via a link and wants to return to the previous page (I don't want to trap anyone).
When I thought about it the best way would be to use anchors. The normal back button supports them and you can go back in history without reloading the page (/#1 <- /#2 <- /#3 etc.)
It would work like this:
Use normal URLs in the link, but catch the click event
When user clicks, load content and attach it to a DIV
Change the window.location, using an anchor (e.g. 'domain.com/#products/women-clothing' with window.location="#products/women-clothing";)
When the window.location changes, get the anchor, read out the path and get the content via ajax, attach it to a DIV
Only the last part isn't really clear for me and I could need help here.
Finaly, my question: Does this make any sense?
Thanks!
Just add the href to window.location.hash after loading the content into a div. Then you can use that back button detection script to load what ever is in the hash.
I solved the problem by using this great jQuery Plugin: History.js
Thanks!