Reputation: 444
I have a simple router:
Erin.Router = Backbone.Router.extend({
initialize: function() {
Backbone.history.start({pushState: true});
},
routes: {
'' : 'index',
'project/:img' :'project',
},
index: function() {
var galleryView = new Erin.GalleryView();
},
project: function(img) {
console.log(img);
}
});
The template for the Erin.GalleryView
is(thinking there might be an issue there):
<script type="text/template" id="gallery-grid">
<a href="/project/<%= id %>">
<img src="<%= thumbnail %>" />
<span class="desc">
<div class="desc-wrap">
<p class="title"><%= title %></p>
<p class="client"><%= client %></p>
</div>
</span>
</a>
</script>
The GalleryView and the GalleryItem code.
Erin.GalleryItem = Backbone.View.extend({
tagName: 'div',
className: 'project-container',
//Grab the template html
template: _.template($('#gallery-grid').html()),
//Set up the render function
render: function() {
//What is the $el in this case?
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
Erin.GalleryView = Backbone.View.extend({
el: '#projects',
initialize: function() {
//create new collection
this.col = new Erin.Gallery();
//Listen to all events on collection
//Call Render on it
this.listenTo(this.col,'all',this.render);
//Fetch data
this.col.fetch();
},
render: function() {
//Get reference to the view object
var that = this;
//Empty div
this.$el.empty();
//For each model in the collection
_.each(this.col.models, function(model){
//call the renderItem method
that.renderItem(model);
},this);
},
renderItem: function(model) {
//create a new single item view
var itemView = new Erin.GalleryItem({
model:model
});
//Append items to to element, in this case "#projects"
this.$el.append(itemView.render().el);
}
});
Then I have a document ready
$(function() {
var router = new Erin.Router();
$('#projects').on('click', 'a[href ^="/"]', function(e){
e.preventDefault();
router.navigate($(this).attr('href'),{trigger: true});
});
});
When you load the page and click one of the links in the #project
section, everything behaves as it should, if you refresh that page however, I get an error that breaks the page.
From the console:
Uncaught SyntaxError: Unexpected token < js/jquery.js:1
Uncaught SyntaxError: Unexpected token < js/underscore-min.js:1
Uncaught SyntaxError: Unexpected token < js/backbone.js:1
Uncaught SyntaxError: Unexpected token < erin.js:1
It also states stuff like:
Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:8888/project/js/backbone.js".
For all the links and scripts in the head of the document.
Which all seem to point at the first line of the index.html file. So if I click a link, it will console the img id I am looking for from my data, if I refresh the page OR type that link in, I get the errors above. Am I correct in thinking I should be able to save the links domain.com/project/coolthing
and have that work when someone comes to the page. Have I missed something? Implemented something weird? A nudge in the right direction would be much appreciated.
Thanks.
Upvotes: 3
Views: 1599
Reputation: 2249
Both thibauts' and providencemac's assessments are right. Either don't use pushState and go with hash links or put a rewrite rule in your server to send the statics.
initially when you load you load this url -
http://localhost:8888
like wise url of your statics is along this
http://localhost:8888/js/backbone.js
the actually problem is when you use pushState and visit a link. Your browser url becomes. something like this -
http://localhost:8888/project/some_img_id
Now when you try to reload the page, the index file is taken from this url -
http://localhost:8888/project/your_default.file [index.html]
Which your server fails to find and defaults to index file at
http://localhost:8888/your_default.file
And when the browser tries to access the statics it again defaults to index file
http://localhost:8888/project/js/backbone.js
thats why the error. as it finds '<' character which is invalid toekn in javascript.
Uncaught SyntaxError: Unexpected token < js/jquery.js:1
this error cause the file its trying to parse is backbone.js a javascript but its gets your index.html
Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:8888/project/js/backbone.js".
Upvotes: 1
Reputation: 1648
You have a problem server-side. You're probably already half-way to the solution.
It looks like you have correctly configured your server to send your app HTML on any hit, except for your assets (js, css) which have precedence.
The problem lies in you main HTML, where your JS files are referenced with a relative path. When you reload after pushState has updated the URL to /project/1
the base URL becomes /project/
.
ie. you have
<script src="js/backbone.js"></script>
when you should have
<script src="/js/backbone.js"></script>
As a result, when the browser tries to load backbone.js it doesn't find it (/project/js/backbone.js doesn't exist), and hits the server catchall that delivers the app HTML (hence the parsing error that chokes on <
).
My explaination may not be crystal clear, it's pretty late over here, but I'm sure you'll understand !
Upvotes: 8
Reputation: 622
The problem is in the href
you are using in the template. The Backbone Router is watching for changes to the hash
portion of the site URL, which is the content after the #
symbol.
So your href should be: <a href="/#project/<%= id %>">
(notice the #
before "project")
In that fashion, you won't even need a click handler at all, the Router will automatically capture the hash change event and route accordingly.
Upvotes: 1