I'm trying to construct a solid Backbone JS experiment, where I have a local JSON data file which contains my pages (a project I'm doing has this sort of requirement anyhow). And I've coded this example so I can have endless nested subpages in the pages data. It seems to be working great. But when it comes to the URLs, I'm a little stuck.
How do I approach giving this multiple level navigation example totally dynamic URLs? What I mean is, correctly using the url property of the models and collections to construct the right URLs for all the top level and nested elements. Is it even possible? I just can't think how to do it.
See a live demo of where I am now: http://littlejim.co.uk/code/backbone/multiple-level-navigation-experiment/
Just so it's easier, the source code is below...
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Multiple Level Navigation Experiment</title>
<script type="text/javascript" src="../../media/scripts/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="../../media/scripts/underscore-min.js"></script>
<script type="text/javascript" src="../../media/scripts/backbone-min.js"></script>
<script type="text/javascript" src="application.js"></script>
<script type="text/javascript">
// wait for the DOM to load
$(document).ready(function() {
App.initialize();
});
</script>
</head>
<body>
<div id="header">
<h1>Multiple Level Navigation Experiment</h1>
<p>Want to get this page structure pulled from JSON locally and have a fully functional multiple level nested navigation with correct anchors.</p>
</div>
<div id="article">
<!-- dynamic content here -->
</div>
</body>
</html>
content.json
{
"pages": [
{
"id": 1,
"title": "Home",
"slug": "home"
},
{
"id": 2,
"title": "Services",
"slug": "services",
"subpages": [
{
"id": 1,
"title": "Details",
"slug": "details",
"subpages": [
{
"id": 1,
"title": "This",
"slug": "this"
},
{
"id": 2,
"title": "That",
"slug": "that"
}
]
},
{
"id": 2,
"title": "Honest Service",
"slug": "honest-service"
},
{
"id": 3,
"title": "What We Do",
"slug": "what-we-do"
}
]
},
{
"id": 3,
"title": "Contact Us",
"slug": "contact-us"
}
]
}
application.js
// global app class
window.App = {
Data: {},
Controller: {},
Model: {},
Collection: {},
View: {},
initialize : function () {
$.ajax({
url: "data/content.json",
dataType: "json",
success: function(json) {
App.Data.Pages = json.pages;
new App.Controller.Main();
开发者_StackOverflow中文版 },
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
}
// main controller class
// when called it should have 'data' in JSON format passed to it
App.Controller.Main = Backbone.Controller.extend({
initialize: function() {
var pagesCollection = new App.Collection.Pages(App.Data.Pages);
var pagesView = new App.View.Pages({collection: pagesCollection});
$('#article').html(pagesView.render().el);
}
});
// pages model class
App.Model.Page = Backbone.Model.extend({
initialize: function() {
if (!_.isUndefined(this.get("subpages"))) {
this.subpages = new App.Collection.Pages(this.get("subpages"));
} // end if
this.view = new App.View.Page({model: this});
},
});
// page collection class
App.Collection.Pages = Backbone.Collection.extend({
model: App.Model.Page
});
// single page view class
App.View.Page = Backbone.View.extend({
tagName: "li",
initialize: function() {
_.bindAll(this, "render");
},
render: function() {
$(this.el).html(_.template("<%=title%>", {title: this.model.get("title")}));
return this;
}
});
// multiple pages view class
App.View.Pages = Backbone.View.extend({
tagName: "ul",
initialize: function() {
_.bindAll(this, "render");
},
render: function() {
var that = this;
this.collection.each(function(page) {
$(that.el).append(page.view.render().el);
if (!_.isUndefined(page.subpages)) {
var subpagesView = new App.View.Pages({collection: page.subpages});
$(that.el).append(subpagesView.render().el);
} // end if
});
return that;
}
});
I'm just needing so right direction on how to do the URLs properly. The idea I'm wanting is that I can setup my controller for routes so it can expect any page of any nested level. The models, collections and nested collections should be able to generate their URLs on their own, but the hash URL must reflect the level.
Ideally, this navigation would go to URLs like these:
- http://example.com/#pages/services
- http://example.com/#pages/services/details
- http://example.com/#pages/services/details/this
...the URLs using the "slug" from the content.json data. Does any of this make sense? I'm pretty new to Backbone JS and just want to do things right. Thanks, James
Here's my favorite solution to this problem: use PathJS !
Why not just parse out the slug?
So you can have a single route in the Backbone.Controller that looks like this:
'pages/:id' : showPage
And then showPage looks like:
showPage(id) : function(id) {
parse out the string 'services/details/etc'
look up the slug data based on that IE pages['services']['details']['etc']
}
or if the pages actually need to be processed differently, you can setup multiple routes, ever more granular like this:
'pages/:id' : showPage
'pages/:id/:nest' : showNestedPage
'pages/:id/:nest/:more' : showNestedMorePage
精彩评论