bit of a weird one and I'm a little baffled...
I have a page, on that page is the following (well, with a few name changes):
$(document).ready(function() {
var router = new App.Routers.ExampleRouter();
Backbone.history.start({pushState: true});
})
The router goes on its way to instantiate some collections, views etc. Everything is working absolutely fine in Chrome, Safari, Firefox and Opera. But not in IE 8 or 9 (maybe 10 too, I haven't tested).
In IE8 or 9 when the page is first requested it starts to load, but as soon as the document is ready (and the router therefore instantiated and History started) the page redirects to the site root.
There's nothing in the console that I can see prior to the redirect. There's no code anywhere else that could be somehow doing it - I mean, we have a large codebase, so it's always a possibility, but there's nothing that deals with routing or the History API that could be conflicting.
The weird part is if the pushState: true
option is removed, the page doesn't redirect, it loads fully as it should - the router doesn't go on its way to do anything as it's now expecting hashbang style routes, but it at least doesn't kick you back to the site's root. Add the option back in, and it breaks again...
So, my first thought was obviously "Well...the History API isn't supported in IE8 or 9...must be it" but then Backbone.js is supposed to revert back to hashbang style URLs for those older browsers, so it can't be that.
What on earth is causing just IE to redirect back to the homepage when dealing with a Backbone.js router?
EDIT
(The below can probably be ignored now as EDIT 2 proves it did nothing, although yay for removing trailing commas)
Okay, so after a little debugging and really clutching at straws I found that the router wasn't actually being instantiated - no initialize method being called, no ability to call custom methods on the router (I'd just made a silly method to alert
and console.log
) and called it just after var router = new App.Routers.ExampleRouter();
.
Calling the method was returning an error along the lines of: "object doesn't support that property or method" (all of this is just IE again, fine in other browsers). This wasn't unique to the router though, I invoked a new model too and did the same things, same thing...just wasn't being "seen". A Google of the object error suggested trailing-commas. Right enough there were some in the codebase, I removed all of them and it seemed like things were going well. All of a sudden the router (and model) were very much there - initialize method called, custom method called etc. I figured the commas may have stopped all of the JS being parsed (we concatenate multiple files).
I'd obviously been doing all of this with the pushState
option removed. I then added pushState: true
back in genuinely thinking that would fix it what with the above having happened. I'd thought at the time "Ah, the router never actually 'existed' so maybe Backbone.History.Start({pushState: true})
being called sent it looking for a route, and none existed due to the router not being instantiated, and the kick-back to the homepage was just some sort of side-effect" but alas, no, the exact same thing is still happening. Add in the pushState: true
option and the page just doesn't load, and kicks you back to the homepage.
EDIT 2
Okay, so I've tried some further things to no avail. I made a completely separate blank page that pulls in jQuery, Backbone.js and Underscore.js via a CDN and contains some barebones JavaScript for creating a router, instantiating it and calling Backbone.History.Start(). The code in it's entirety for that page is:
<!DOCTYPE html>
<html>
<head>
<title>Test IE</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery-1.8.0.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script>
$(document).ready(function(){
App = {
Routers: {
}
};
App.Routers.RouterTest = Backbone.Router.extend({
routes: {
"ietest.html" : "helloWorld"
},
initialize: function() {
console.log("router init");
},
helloWorld: function() {
alert("helloWorld!")
}
});
router = new App.Routers.RouterTest();
Backbone.history.start({pushState: true});
});
</script>
</head>
<body>
</body>
</html>
That's it, completely barebones, no influence from any other site assets etc. The exact same thing still happens. All browsers do what is expected, except IE (tested on 8 and 9) which again starts to load the page, then executes the route and all of a sudden redirected back to the homepage. If I turn pushState off and use hashbangs everything works as expected - so routing does 'work' for me in IE, just not with pushState set to true.
I can't see that this is a front-end thing anymore as I've stripped away everything I can? Is there any way this is a server related thing? The back-end is Ruby on Rails and the problem is exhibited locally and on staging / live servers. Or have I grossly misunderstood the way that Backbone.js degrades pushState to hashbangs with IE?
EDIT 3