I'm working on converting a series of interactive educational apps from Flash to Javascript, and my team is planning on using Backbone.js as the framework. Each of these apps is basically a collection of scenes that present information to the user and/or prompt some interaction, either in the form of questions or interactive widgets. The basic structure we're considering for the app is as follows:
- a set of JSON files that contain the particular information for each app, such as how many different "scenes" or objects the app has, the different messages and/or widgets displayed to users, etc.
- a set of Backbone (probably Underscore) templates governing how to display navigation, messages, etc.
- a collection of Backbone views / routers / models to facilitate navigating between scenes in an app and handling user interaction
- some interactive widgets built in native Javascript
Trouble is, of course, is that I'm a novice when it comes to Backbone. I've made my way through some of the basic tutorials but am having trouble integrating Backbone with static JSON files.
Let's say I have the following very basic JSON file that lays out three scenes to be displayed:
var scenes = [
{
"name": "Introduction",
"label": "Introduction",
"message": "Welcome to this app"
},
{
"name": "Exercise",
"label": "Exercise",
"message": "If this were a real app, there'd be some sort of exercise here"
},
{
"name": "Conclusion",
"label": "Conclusion",
"order": "Thank you for completing this app"
}
]
What I need, and what I'm trying to do, is to have Backbone generate a navigation widget that lets users navigate between these scenes and to display the message for each scene. (This is obviously an incredibly simplified version of the real-world app.)
Here's what I've tried:
// simplified object containing stage information
var stages = [
{
"name": "Introduction",
"label": "Introduction",
"message": "Welcome to this app"
},
{
"name": "Exercise",
"label": "Exercise",
"message": "If this were a real app, there'd be some sort of exercise here"
},
{
"name": "Conclusion",
"label": "Conclusion",
"order": "Thank you for completing this app"
}
];
$(function(){
// create model for each stage
StageModel = Backbone.Model.extend({});
// create collection for StageModel
StageModelList = Backbone.Collection.extend({
model: StageModel
});
var stageModelList = new StageModelList();
// create view for list of stages
StageListView = Backbone.View.extend({
el: $("#stageNav"),
initialize: function() {
// if stages are added later
stagemodellist.bind('add',this.createStageList, this);
},
events: {
'click .stageListItem' : 'selectStage'
},
createStageList: function(model) {
$("#stageList").append("<li class='stageListItem'>"+model.label+"</li>");
},
selectStage: function() {
this.router.navigate("stage/"+this.stage.name,true);
}
});
// create view for each stages
StageView = Backbone.View.extend({
el: $("#stage"),
initialize: function(options) {
// get stage variable from options
this.stage = this.options.stage;
// display stage
createOnEnter(this.stage);
},
createOnEnter: function(stage) {
$("#stageLabel").html(stage.label);
$("#stageMsg").html(stage.message);
}
});
// create router
AppRouter = Backbone.Router.extend({
initialize: function() {
Backbone.history.start();
// create collection
new StageModelList();
// create view when router is initialized
new StageListView();
// loop through stages and add each to StageModelList
for (var s in stages) {
StageModelList.add(stages[s]);
}
},
routes: {
"stage/:stage" : "renderStage"
},
renderStage: function(stage) {
// display StageView for this stage
new StageView({stage:stage});
}
});
var App = new AppRouter();
});
And the html:
<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script class="jsbin" src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script class="jsbin" src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="js/ilo4.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<p>My pathetic attempt at a Backbone.js app</p>
<div id="stageNav">
<ul id="stageList">
</ul>
</div>
<div id="stage">
<div id="stageLabel">
</div>
<div id="stageMsg">
</div>
</div>
</body>
</html>
(You can also see a jsbin version here: http://jsbin.com/iwerek/edit#javascript,html,live).
Right now this doesn't do anything, unfortunately.
I know that I'm doing so many things wrong here, and some questions that I'm kicking around:
- Do I even need a router?
- Do I need to initialize the collection as a variable?
- Is there a better way to bind the model to the list of stages?
A