I'm building a Backbone.js app with hash based navigation. It works fine everywhere except IE7. In IE7, when I click on a link that changes the hash, what happens is:
the page changes
the hash then reverts to the previous value
the page changes to the previous page as well
I made the links work by adding saveLocation calls to the controller after loading each page, however when I use the back button or reload the page, it always takes me to the home page instead of going back or reloading the current page.
What can I do to make the back button and page reloading work?
I made some changes to backbone to make it work for me. You can have a look at my repo here:
https://github.com/juggy/backbone
Works for me so far. I dunno if I broke anything else. I inspired myself from YUI and https://github.com/cowboy/jquery-hashchange/blob/master/jquery.ba-hashchange.js .
I also had same IE7 problem with you, and tried every way (saveLocation things, Backbone patches, etc).. but it didn't work out. It seems IE7 misunderstand when switching thru many pages.
My final solution was not to use Backbone.history but jQuery History Plugin.
http://tkyk.github.com/jquery-history-plugin/
I know this is the worst workaround because this solution relies on other plugin, but fortunately, Backbone.Controller just handles routings and state handling that you don't have to use it.
jQuery History Plugin just works.
An answer has been posted in Backbone.js cause bug only in IE7.
Related
The Scenario
I'm developing the front-end (CSS only) of an Angular SPA.
I'm not especially familiar with Angular routing.
I'd like to add a standalone page containing Bootstrap components just for development purposes (yes, I know this means it won't be a single page application anymore). This way I have one unified view with all the components so I don't have to switch back and forth while working on the CSS. It also acts as documentation for the Bootstrap for the other devs to refer to.
What I've tried
I originally added a bootstrap.html page to the app folder, alongside the app's index.html This worked at first, but has now stopped working. What would be the best/standard way to achieve something like this?
Update: I've managed to fix some of the JS errors, so the page is up and running again. My question remains though: "is there a way of adding a standalone page that is considered standard/best practise, or is it literally just add a separate HTML page at the app root?"
If you use a target='_self' in your linking anchor tag, this should force a full page reload, and that will avoid the angular routing - which is where I expect your request is getting hijacked (by design).
e.g.
link
Answering your updated question
Not to my knowledge, since (as you correctly pointed out) this mixes the SPA design pattern.
The biggest problem is that I even don't really know how to describe the problem I'm asking about. It's the first time in more then a decade of wed development.
I'm working on a Rails 4.1.1 app and using angularjs pretty extensively, though I don't know it well yet. And everything seemed to be working fine up to the moment when I tried to add some browser history manipulation to my app (e.g. changing the displayed url when listing though a paginated list so that that url can be copied and distributed). To do this I added a config to my app.
#app.config ($locationProvider) ->
$locationProvider.html5Mode(true)
And then in my angular controller added the $location binding like this
$scope.$watch 'pagination.cur', (newVal) ->
$scope.loadNews newVal
$location.path("/news").search({page:newVal})
(this is ment to change the url in the browser searchbox when the user goes from one page to another).
That workes well, the url does change appropriately, but all the sudden all the html links on the page got broken. I mean litteraly. I click any link on the page (even outside the controller div), the url in the serchbox changes appropriately, but the turbolinks toes not fire the Ajax request to get the new page content. If I then refresh the page, it loads the correct page.
I know it's really weird. What's weirder, that I don't get any JavaScript errors or anything unusual.
The only way I found to get the links working again - is to remove that initial config.
But when I do it, the $location falls back to hashtag syntax, wich is really not at all what I want.
My only assumption is that there could be some kind of a conflict between angular $location service and turbolinks when handling browser history, but even if that's right, I have no idea how to get around it. And I really need that kind of manipulation, 'cause I'm going to be using it alot in this and other apps.
I really don't know, what other information on this problem may be usefull, don't hasitate to ask for updates. I'll post whatever I can.
P.S. Btw, can this kind of manipulation be done by means of turbolinks? 'Cause it's exactly the same thing turbolinks does when changing the displayed url after page body reload, but I can't find any documentation on its public API for that.
UPDATE
Have no idea what's the source of the problem yet, but it seems to be not related to the turbolinks gem. Removing turbolinks requirements from the application.js file does not change anything.
Using $window.history.pushState instead of $location.path solves the functionality problem, but does not explain the initial bug.
I was setting up a simple router in Backbone.js while I noted an issue, I googled for a long time and found some solutions.
The problem is that whenever I navigate to a url, this url will work while I'm inside the app itself, but once you bookmark it and return it will obviously return a 404 since that page doesn't exist.
Backbone.history.navigate('test', true);
This will navigate to http://www.domain.com/test, which is great, but once you refresh the same URL it returns a 404.
There are ways to get this to work with using a specific .htaccess file, but I'm building this inside an existing website, so I can't use this.
Is there a way in Backbone.js to revert to just using hashbangs? My url would then look like this `http://www.domain.com/#!/test
This might not be the cleanest URL, but at least it will work.
Or am I just missing something obvious here? It can't be that I'm the only person with this problem.
You're using pushState according to your url, so you've got 2 main options:
stop using pushState when starting Backbone history (which would be the equivalent of using a hashbang, except for SEO)
have your server return a page for every URL your app generates (it can be the same exact page)
In the second case, if you don't care about SEO, you can have a catch all rule always returning (e.g.) index.html containing your Backbone app. When you start Backbone's history, it will lokk at the URL and navigate to the proper page (although you might have a "double render" effect).
If you're worried about SEO, you need to return page content for SEO along with your Backbone app.
What is the purpose of Backbone's Router? Can't we do the same thing without it? With a router, a click on a link would change the URL of a page and the last bits of the URL would trigger a function. Why not just assign a click event on this link and trigger a function there?
I don't use backbone specifically, (rather, I use iron-router for my project) but it's purpose is to route URLs to pages. Consider the following: you have 50 links scattered across your website's source all pointing to /awesomePlace (which serves awesomePlace.html). You've decided awesomePlace isn't so awesome anymore and have declared that there is a moreAwesomePlace.html. You could go in and change each of those 50 links to /moreAwesomePlace or you could change the route once. The router could then serve up moreAwesomePlace.html whenever anybody visits /awesomePlace.
That's just one example. I personally haven't spent too much time with routers yet but I'm sure somebody can give some better examples than I have. Hopefully this helps explain things a bit though.
Yes, we can implement same functionalities without router, router is just an helper utility, just like JQuery for DOM manipulations. Reason behind using router all about scalability and flexibility. If you follow "on click do some thing", it does't scale. In a single page application every click might have multiple handlers. One click on item might demand changes to multiple widgets. with routers you can add/remove hooks for the same click. And in future if you want to change the implementation of Router or hooks, you are free to do that, only thing that you need to make sure is contract btw these two remain same.
I updated angularjs to 1.2.0-rc1 and added in ng-route as a dependency and added the angular-route.js file. In this build it is now separate.
Clicking on a link for example that has a bookmark href assigned which i used for bootstrap..
href="#collapse1"
Now angularjs is actually trying to change the route to #/collapse1
Is this a bug or am i missing something
Can anyone help?
Is there some additional configuration that i need to do to stop this from happening ?
Expected behavior
The expected behavior is what happens in angular before (i think i was using 1.0.8) ... the link does nothing as far as angularjs is concerned i.e. NO ROUTE CHANGE, of course bootstrap picks does its own thing and shows an accordion in this example.
This angularjs feature.
Use
href="#/#collapse1"
for correct location change.
because i had the same problem. At my point Bootstrap wasn't loaded and so he tried to route this collaps as an route. After i loaded bootstrap manuel to this view, it works fine.
Hope you understand my bad english ;)