I'm new to javascript and backbone.js
I want to create simple web page with 10 squares with form that will take square id and color.
So every square must have its own style in CSS.
I tried to make it with 10 templates. But script doesn't work at all.
Here is my code:
alert("script entry");
$(function () {
blocks = [
{number: "1", state: "block1" },
{number: "2", state: "block2" },
{number: "3", state: "block3" },
{number: "4", state: "block4" },
{number: "5", state: "block5" },
{number: "6", state: "block6" },
{number: "7", state: "block7" },
{number: "8", state: "block8" },
{number: "9", state: "block9" },
{number: "10", state: "block10" },
];
var BlockModel = Backbone.Model.extend({
defaults:{
"state": "block1",
"number": "1"
}
});
var BlockCollection = Backbone.Collection.extend({
model: BlockModel,
});
var blockNumbers = new BlockCollection([
model:BlockModel
]);
var BlockView = Backbone.View.extend({
tagName: "blockTag",
className: "blockClass",
templates: {
"block1": _.template($('#block1').html()),
"block2": _.template($('#block2').html()),
"block3": _.template($('#block3').html()),
"block4": _.template($('#block4').html()),
"block5": _.template($('#block5').html()),
"block6": _.template($('#block6').html()),
"block7": _.template($('#block7').html()),
"block8": _.template($('#block8').html()),
"block9": _.template($('#block9').html()),
"block10": _.template($('#block10').html())
},
render: function () {
var state= this.model.get("state");
var tmpl = this.templates(state);
$(this.el).html(tmpl(this.model.toJSON()));
return this;
}
});
var appView = Backbone.View.extend({
el: $("#block"), //большой контейнер
initialize: function(){
this.collection = new blockNumbers(blocks);
this.render();
},
render: function(){
_.each(this.collection.models, function () {
that.renderBlock(this.model);
}, this);
},
renderBlock: function (inputModel) {
var blockView = new BlockView({
{model: inputModel}
});
this.$el.append(blockView.render().el);
}
});
var app = new appView();
});
Where is my error?
My index.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TEST</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="block">
<script type="text/template" id="block1">
<div class="block1"><%=number%></div>
<div class="buttonplace">
<input type="button" value="check" />
</div>
</script>
<script type="text/template" id="block2">
<div class="block2"><%=number%></div>
</script>
<script type="text/template" id="block3">
<div class="block3">3</div>
</script>
<script type="text/template" id="block4">
<div class="block4">4</div>
</script>
<script type="text/template" id="block5">
<div class="block5">5</div>
</script>
<script type="text/template" id="block6">
<div class="block6">6</div>
</script>
<script type="text/template" id="block7">
<div class="block7">7</div>
</script>
<script type="text/template" id="block8">
<div class="block8">8</div>
</script>
<script type="text/template" id="block9">
<div class="block9">9</div>
</script>
<script type="text/template" id="block10">
<div class="block10">10</div>
</script>
</div>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="backbone.js"></script>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
There are several problems with your code, primarily you are using parentheses in some cases instead of brackets [ and instead of curly braces {. You also have some extra trailing commas. Further in your HTML your closing tag for the block div should be before all your script templates.
For example
var blockNumbers = new BlockCollection([
model:BlockModel
]);
Should be
var blockNumbers = new BlockCollection({
model:BlockModel
});
And
var tmpl = this.templates(state);
Should be
var tmpl = this.templates[state];
In addition in your appView you are trying to instantiate a new instance of your instance
this.collection = new blockNumbers(blocks);
While you probably meant to do
this.collection = new BlockNumbers(blocks);
Here's a working jsBin
Aside from all that you have a lot of repetition with your templates, you can really consolidate them all into one or two templates.
For example you can just have one template for blocks with a button and one for blocks without a button and update the blocks state accordingly
<script type="text/template" id="blockWithButton">
<div class="block<%=number%>"><%=number%></div>
<div class="buttonplace">
<input type="button" value="check" />
</div>
</script>
<script type="text/template" id="blockWithoutButton">
<div class="block<%=number%>"><%=number%></div>
</script>
Another jsbin
templates: {
"block1": _.template($('#block1').html()),
...
"block10": _.template($('#block10').html())
},
you have defined an object above.
var tmpl = this.templates(state);
but you call it as a function.
you may get the templates as this.templates[state];
UPDATE
I think you can just use the same template as:
<script type="text/template" id="block">
<div class="block<%=number%>"><%=number%></div>
<div class="buttonplace">
<input type="button" value="check" />
</div>
</script>
and you can simplfy your model like this, too.
Of course, if you need.
UPDATE
You may new a Collection with some options out of single {} but not [] or more {}s, like this:
var blockNumbers = new BlockCollection({
model:BlockModel
});
...
var blockView = new BlockView({
model: inputModel
});
not:
var blockNumbers = new BlockCollection([
model:BlockModel
]);
...
var blockView = new BlockView({
{model: inputModel}
});
UPDATE
the blockNumbers is an instance of Collection, you can't fetch data for it by new like:
this.collection = new blockNumbers(blocks);
You should assign the bolckNumbers to this.collection, and give it an url , then call sync() or fetch() to get the data, then render it.
END
Lastly, I have found too much mistake of basics above, Backbone.js is simple but hard, you ought to be able to solve it yourself, it is useful to you.
Thanks.
Related
On my page I have a dynamic list of musicians (players) whereas a player can be removed and added to the list. Each player shall have multiple instruments which is also a dynamic list, whereas an instrument can be added or removed from a player's instrument list. So we are talking about two nested dynamic lists.
Here is the code and the problem description under it.
jamorg.html:
<!DOCTYPE html>
<html ng-app='jamorgApp'>
<head>
<link rel="stylesheet" type="text/css" href="C:\Users\jazzblue\Documents\Bootstrap\bootstrap-3.3.2-dist\css\bootstrap.min.css" />
<title>Jam Organizer</title>
</head>
<body>
<div ng-controller='JamOrgController as jamOrg'>
<h1>Jam</h1>
<div ng-repeat='player in players'>
<div>
<h3 style="display: inline-block;">player {{$index}}</h3>
<button ng-click="removePlayer($index)">Remove</button>
</div>
<br/>
<div ng-controller='JamOrgPlayerController as jamOrgPlayer'>
<div ng-repeat='instrument in player'>
<span>Instrument: {{instrument.instrument}},</span>
<span>Level: {{instrument.level}}</span>
<button ng-click="remove($index)">Remove</button>
</div>
<button ng-click="addInstrument()">Add Instrument</button>
Instrument: <input ng-model='newInstrument.instrument'>
Level: <input ng-model='newPlayer.level'>
</div>
</div>
</div>
<script type="text/javascript" src="C:\Users\jazzblue\Documents\AngularJS\angular.min.js"></script>
<script type="text/javascript" src="jamorgApp.js"></script>
</body>
</html>
jamorgApp.js
var app = angular.module('jamorgApp', []);
app.controller('JamOrgController', ['$scope', function($scope){
$scope.players = players;
$scope.removePlayer = function(index) {
$scope.players.splice(index, 1);
}
}]);
app.controller('JamOrgPlayerController', ['$scope', function($scope){
$scope.newInstrument = newInstrument;
$scope.remove = function(index) {
$scope.player.splice(index, 1);
}
$scope.addInstrument = function() {
$scope.player.push(newInstrument);
}
}]);
var players = [
[{instrument: 'Guitar', level: 3}, {instrument: 'Keyboard', level: 3}],
[{instrument: 'Bass', level: 4}],
[{instrument: 'Drums', level: 3}]
];
var newInstrument = [
{instrument: 'x', level: 'y'}
]
Here is my problem: the same newInstrument is being added to all the different players lists which is wrong: each player's instrument list should have its own newInstrument.
How should I change it to get the right design?
Thanks!
Where you do:
$scope.addInstrument = function() {
$scope.player.push(newInstrument);
}
Try doing:
$scope.addInstrument = function() {
$scope.player.push(angular.copy(newInstrument));
}
Update:
In your HTML:
<button ng-click="addInstrument(player)">Add Instrument</button>
In your JS:
$scope.addInstrument = function(player) {
player.push(angular.copy(newInstrument));
}
UPDATE
I created a fiddle where you can check some possible modifications to your code. It uses just one controller and fixes the duplicated object issues.
<button ng-click="addInstrument($index)">Add Instrument</button>
Instrument: <input ng-model='newInstrument.instrument'>
Level: <input ng-model='newPlayer.level'>
and your addInstrument function should be like this
$scope.addInstrument = function(index) {
$scope.players[index].push($scope.newInstrument);
}
I want to display data from JSON using a backbone script.
This is the html Page:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<script src="backbone.js"></script>
<script src="jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var Profile = Backbone.Model.extend();
var ProfileList = Backbone.Collection.extend({
model: Profile,
url: 'document.json'
});
var ProfileView = Backbone.View.extend({
el: "#profiles",
template: _.template($('#profileTemplate').html()),
initialize: function(){
this.listenTo(this.collection,"add", this.renderItem);
},
render: function () {
this.collection.each(function(model){
var profileTemplate = this.template(model.toJSON());
this.$el.append(profileTemplate);
}, this);
return this;
},
renderItem: function(profile) {
var profileTemplate = this.template(profile.toJSON());
this.$el.append(profileTemplate);
}
});
var profileList = new ProfileList();
var profilesView = new ProfileView({ collection: profileList });
profilesView.render();
});
</script>
</head>
<body>
<div id="profiles"></div>
<script id="profileTemplate" type="text/template">
<div class="profile">
<div class="info">
<div class="name">
<%= name %>
</div>
<div class="title">
<%= title %>
</div>
<div class="background">
<%= background %>
</div>
</div>
</div>
<br />
</script>
</body>
</html>
This is my json data:
document.json
[
{
"id": "p1",
"name" : "AAAA",
"title" : "BBBB",
"background" : "CCCC"
},
{
"id": "p2",
"name" : "DDDD",
"title" : "EEEE",
"background" : "FFFF"
},
{
"id": "p3",
"name" : "GGGG",
"title" : "HHHH",
"background" : "IIII"
}
]
There's nothing being displayed on the page.
Am I missing something?
I have been trying to get the JSON data printed on the div element in specified HTML. But Nothing being displayed. I tried debugging the code, I could insert alert statement before Backbone.Model.extend inside document.ready in jquery. But when I put alert statement inside it, it isnt coming up. So, the code inside Backbone.Model.extend must be gone wrong somewhere.
Somebody help me?
You need to check the order of loading your scripts, jquery should come first, underscore secondly (since you are using undescore.js templating) then backbone:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
If that doesn't solve your problem then you could either try sending in a static reference to your initial set of data, then call fetch() as needed to grab more, or you can call fetch explicitly as follows:
var profileList = new ProfileList();
var profilesView = new ProfileView({collection: profileList});
profileList.fetch();
profileList.bind('reset', function () {
profilesView.render();
});
Working Demo
You should load scripts in order, jquery, underscore and then Backbone
index.html
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="js/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="js/lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
<link href="js/lib/ratchet/ratchet-theme-ios.css" rel="stylesheet">
<link href="js/lib/ratchet/ratchet.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title>totter</title>
</head>
<body>
<div class="content">
</div>
<script src="js/lib/jquery-1.9.1.min.js"></script>
<script src="js/lib/underscore-min.js"></script>
<script src="js/lib/backbone-min.js"></script>
<script src="js/lib/bootstrap/js/bootstrap.js"></script>
<script src="js/lib/handlebars/handlebars-v1.3.0.js"></script>
<script src="js/lib/ratchet/ratchet.js"></script>
<script src="js/common/helper.js"></script>
<script src="js/app.js"></script>
<script src="js/views/home.js"></script>
<script src="js/views/signin.js"></script>
<script src="js/models/home.js"></script>
<script src="js/models/signin.js"></script>
</body>
</html>
app.js
var app = {
views: {},
models: {},
loadTemplates: function(views, callback) {
var deferreds = [];
$.each(views, function(index, view) {
if (app[view]) {
deferreds.push($.get('template/' + view + '.hbs', function(data) {
app[view].prototype.template = _.template(data);
}, 'html'));
} else {
alert(view + " not found");
}
});
$.when.apply(null, deferreds).done(callback);
}
};
app.Router = Backbone.Router.extend({
routes: {
"": "home",
"signIn":"SignIn"
},
home: function () {
// Since the home view never changes, we instantiate it and render it only once
if (!app.home) {
app.home = new app.HomeView();
app.home.render();
} else {
// delegate events when the view is recycled
app.home.delegateEvents();
}
},
SignIn:function(){
if (!app.signin) {
app.signin = new app.SignInView();
app.signIn.render();
} else {
// delegate events when the view is recycled
app.signin.delegateEvents();
}
}
});
$(document).on("ready", function () {
app.loadTemplates(["HomeView"],
function () {
app.router = new app.Router();
Backbone.history.start();
});
});
home.js
app.HomeView = Backbone.View.extend({
//Calling the render method to render view from the template
initialize:function(){
this.render();
},
//Pass the handlebars template for complilation and
render: function () {
var path = './template/HomeView.hbs';
Helper.GET_TEMPLATE(path, function(template) {
//pass collection to template to set values
var html = template(app.homeCollection.toJSON());
//pass collection to template to set values
$('.content').html(html);
});
$('.signin').bind('click', function(e) {
app.Router.navigate("signIn", {trigger: true});
});
}
});
app.home = new app.HomeView();
sigin.js
app.SigInView = Backbone.View.extend({
//Calling the render method to render view from the template
initialize:function(){
this.render();
},
//Pass the handlebars template for complilation and
render: function () {
var path = './template/SignInView.hbs';
Helper.GET_TEMPLATE(path, function(template) {
//pass collection to template to set values
var html = template(app.signinCollection.toJSON());
//pass collection to template to set values
$('.content').html(html);
});
}
});
app.signin = new app.SigInView();
helper.js
var Helper = {};
Helper.GET_TEMPLATE = function(path,callback){
var source, template;
$.ajax({
url: path,
success: function(data) {
source = data;
//Compile the raw data we got from the file
template = Handlebars.compile(source);
//execute the callback if passed
if (callback){
callback(template);
}
}
});
}
homeModel.js
var HomeModel = Backbone.Model.extend();
var homeData = new HomeModel({
id: 1,
signUpTitle: 'Sign Up for TOT ',
signInTitle: 'Sign In',
slogan:'slogan slogan slogan slogan slogan slogan slogan slogan slogan slogan '
});
/**
* Defining a Collection to set model
*/
var HomeCollection = Backbone.Collection.extend({
model: HomeModel
});
/**
* Defining a array to hold the collection
*/
app.homeCollection = new HomeCollection([homeData]);
HomeView.hbs
<header class="bar bar-nav">
<h1 class="title">totter</h1>
</header>
<div class="logo">
<img src = "img/choice.png">
</div>
{{#each []}}
<div class="textcontent">
<label>{{this.slogan}}</label>
</div>
<div class="footer">
<button class="btn btn-primary btn-block signup" style="">{{this.signUpTitle}}</button>
</div>
<div class="footer">
<button class="btn btn-primary btn-block signin">{{this.signInTitle}}</button>
</div>
{{/each}}
In the above code I used to develop a simple app with 2 views. I want to show sign-in view on button click of sign-in.
How can I achive this? I am using "handlebars" and "backbone.js".
The events aren't firing because you're utilizing the View el property. Either give it a preexisting element or insert the el itself to the DOM.
see the answer on the following discussion for a more comprehensive explanation.
I'm trying to write a pretty simple app: I have some games (say chess, tictactoe... whatever), and there are several boards of each game. I want to show a list of games, and then show a list of boards when you click on a game.
But I'm facing a lot of problems. I'll first describe them, and I'll paste the code after that:
The list of games is correctly shown. No problem here.
When I click a game, I get this error:
Uncaught Error: assertion failed: an Ember.CollectionView's content must implement Ember.Array. You passed <(generated game controller):ember237>
BUT if I press F5 or write the URL manually, everything works fine. And I have no idea why.
UPDATE: I've seen that if I change the games template, changing the {{#linkTo}} with a hand-written link, everything works OK:
This is the non-working linkTo: {{#linkTo 'game' game}}{{game.name}}{{/linkTo}}. It builds the URL correctly, but it fails when I click on it.
This is a hand-written <a> tag: {{game.name}}. It works perfectly.
The Url of each board should follow this format:
/games/1/boards/5
But when I write the {{#linkTo 'board' board}} what I get is:
/games/undefined/boards/5
Here is the code (You can see a "working" copy here in JBin. But it's not functional, because it relays on a local REST app):
The Router:
MGames.Router.map(function () {
this.resource('games', function () {
this.resource ('game', {path: '/:game_id'}, function () {
this.resource('board', {path: '/boards/:board_id'});
});
});
});
MGames.IndexRoute = Ember.Route.extend({
redirect: function () {
this.transitionTo('games');
}
});
MGames.GamesRoute = Ember.Route.extend ({
model: function() {
return MGames.Game.findAll();
}
});
MGames.GameRoute = Ember.Route.extend ({
model: function(params) {
return MGames.Board.findAllByGame(params.game_id);
}
});
MGames.BoardsRoute = Ember.Route.extend ({
model: function(params) {
return this.modelFor('game').then(
function (game) {
return MGames.Board.find(game.get('id'), params.board_id);
}
);
}
});
The models:
MGames.Game = Ember.Object.extend({
id: null,
name: null,
icon: null
});
MGames.Game.reopenClass({
findAll: function() {
var url = [MGames.GAMES_API_URL];
url.push ('games');
url = url.join('/');
var result = Ember.ArrayProxy.create({ content: [] });
$.getJSON(url).then (
function (response) {
response.forEach(function (child) {
result.pushObject (MGames.Game.create(child));
});
}
);
return result;
},
find: function (id) {
var url = [MGames.GAMES_API_URL];
url.push ('games');
url.push (id);
url = url.join('/');
var game = MGames.Game.create({ isLoaded: false });
$.getJSON(url).then (
function(response) {
game.setProperties(response);
game.set('isLoaded', true);
}
);
return game;
}
});
MGames.Board = Ember.Object.extend({
id: null,
name: null,
owner: null,
game: null,
is_public: null,
created_at: null
});
MGames.Board.reopenClass({
findAllByGame: function (game) {
var url = [MGames.GAMES_API_URL];
url.push ('games');
url.push (game);
url.push ('boards');
url = url.join('/');
var result = Ember.ArrayProxy.create({ content: [] });
$.getJSON(url).then (
function (response) {
console.log (response);
response.forEach(function (child) {
result.pushObject (MGames.Board.create(child));
});
}
);
return result;
},
find: function (game, board) {
url = [MGames.GAMES_API_URL];
url.push ('games');
url.push (game);
url.push ('boards');
url.push (board);
url = url.join('/');
var result = MGames.Board.create();
$.getJSON(url).then (
function(response) {
result.setProperties(response);
}
);
return result;
}
});
And the template:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>MGames</title>
<link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<script type="text/x-handlebars">
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active">{{#linkTo 'index' class="brand"}}MGames{{/linkTo}}</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="games">
<div class="row">
<header id="header">
<h1>Games</h1>
</header>
<ul>
{{#each game in controller}}
<li>
{{#linkTo 'game' game}}{{game.name}}{{/linkTo}}
</li>
{{/each}}
</ul>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="game">
<div class="row">
<div class="span3" id="boards">
<header id="header">
<h1>Boards</h1>
</header>
<ul id="board-list">
{{#each board in controller}}
<li>
{{#linkTo 'board' board}}{{board.name}}{{/linkTo}}
</li>
{{/each}}
</ul>
</div>
<div class="span9">
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" id="board">
<header id="header">
<h1>{{game.name}} - {{name}} <small>{{owner.nickname}}</small></h1>
</header>
</script>
<script src="js/libs/jquery.js"></script>
<script src="js/libs/bootstrap.js"></script>
<script src="js/libs/handlebars.js"></script>
<script src="js/libs/ember.js"></script>
<script src="js/application.js"></script>
<script src="js/router.js"></script>
<script src="js/models/game.js"></script>
<script src="js/models/user.js"></script>
</body>
</html>
Ok, I finally figured out the problem. In my gameRoute I wrote this:
MGames.GameRoute = Ember.Route.extend ({
model: function(params) {
return MGames.Board.findAllByGame(params.game_id);
}
});
It worked when I write the URL directly in the browser bar, because Ember calls the model function, but when following a {{#linkTo}} the model is the one passed as parameter, so the modelfunction isn't called.
So the working code is this one (a little bit simplified):
MGames.GameRoute = Ember.Route.extend ({
model: function (params) {
// This is only called when loading the URL directly,
// not following a link. We load the game, and in the
// setupController we'll load the boards.
return MGames.Game.find(params.game_id);
},
setupController: function(controller, game) {
// This is *always* called, so we load the boards
model = MGames.Board.findAllByGame(game.id);
controller.set('model', model);
}
});
The board route that you are linking to has 2 dynamic segments, but you are providing only one. You need to change to,
{{#linkTo 'board' game board}}The board{{/linkTo}}
The undefined error is probably due to the ArrayController not getting a board as the corresponding game id is being passed as undefined. The above change should fix that too.
I am doing a very simple Backbone app example and I keep getting a JS error message. I basically have two files:
app.js
This file creates a Backbone.js app the appends a span from a template using data from a collection view to an already created div on the html file.
/*Backbone.js Appointments App*/
App = (function($){
//Create Appointment Model
var Appointment = Backbone.Model.extend({});
//Create Appointments Collection
var Appointments = Backbone.Collection.extend({
model: Appointment
});
//Instantiate Appointments Collection
var appointmentList = new Appointments();
appointmentList.reset(
[{startDate: '2013-01-11', title: 'First Appointment', description: 'None', id: 1},
{startDate: '2013-02-21', title: 'Second Appointment', description: 'None', id: 2},
{startDate: '2013-02-26', title: 'Third Appointment', description: 'None', id: 3}
]
);
//Create Appointment View
var AppointmentView = Backbone.View.extend({
template: _.template(
'<span class="appointment" title="<%= description %>">' +
' <span class="title"><%= title %></span>' +
' <span class="delete">X</span>' +
'</span>'
),
initialize: function(options) {
this.container = $('#container');
},
render: function() {
$(this.el).html(this.template(this.model));
this.container.append(this.el);
return this;
}
});
var self = {};
self.start = function(){
new AppointmentView({collection: appointmentList}).render();
};
return self;
});
$(function(){
new App(jQuery).start();
});
index.html
This file just calls the jquery, backbone and other js libraries and also created the div container where the Backbone.js app from the previous file will append the data.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello-backbonejs</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.6/underscore-min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js"></script>
<script src="app.js" type="text/javascript"></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
The error I get is the following:
Uncaught TypeError: Object [object Object] has no method 'reset' app.js:14
App app.js:14
(anonymous function) app.js:49
e.resolveWith jquery.min.js:16
e.extend.ready jquery.min.js:16
c.addEventListener.z jquery.min.js:16
You use Backbone 0.3.3 but Collection.reset was introduced in Backbone 0.5. See the changelog for more information.
Either upgrade Backbone (0.9.9 at the moment) (and Underscore and jQuery while you're at it) or use Collection#refresh if you absolutely have to keep Backbone 0.3.3 (but you will probably trip other errors down the road).