有人告诉我,我的项目应该在各自的文件夹中分离模型,视图和集合。这应该是一个简单的修复,但我不知道如何做到这一点,并让我的代码仍然可以运行。
这是我的JAVASCRIPT:
$(function() {
var Food = Backbone.Model.extend({
defaults: {
title: 'no information found',
brand: 'no information found',
calories: 'no information found',
}
});
var AllFoods = Backbone.Firebase.Collection.extend({
model: Food,
url: "https://blinding-torch-8751.firebaseio.com/allfoods"
});
var Breakfast = Backbone.Firebase.Collection.extend({
model: Food,
url: "https://blinding-torch-8751.firebaseio.com/breakfast"
});
var Lunch = Backbone.Firebase.Collection.extend({
model: Food,
url: "https://blinding-torch-8751.firebaseio.com/lunch"
});
var Dinner = Backbone.Firebase.Collection.extend({
model: Food,
url: "https://blinding-torch-8751.firebaseio.com/dinner"
});
var Snack = Backbone.Firebase.Collection.extend({
model: Food,
url: "https://blinding-torch-8751.firebaseio.com/snack"
});
var SearchList = Backbone.Collection.extend({
initialize: function() {
this.bind("reset", function(model, options) {
console.log("Inside event");
console.log(model);
});
},
//** 1. Function "parse" is a Backbone function to parse the response properly
parse: function(response) {
//** return the array hits inside response, when returning the array
//** we let Backone populate this collection
return response.hits;
}
});
var App = Backbone.View.extend({
el: 'body',
events: {
"input #searchBox": "prepCollection",
"click #listing li": "track",
"click #add": "addClicked",
"click #remove": "removeClicked"
},
initialize: function() {
//set up variables used more globally
this.foodid = "";
this.model = new SearchList();
this.foods = new AllFoods();
this.breakfastlist = new Breakfast();
this.lunchlist = new Lunch();
this.dinnerlist = new Dinner();
this.snacklist = new Snack();
this.$total = $('#total span');
this.$list = $('#listing');
this.$instruct = $('#instruct');
this.$tracked = $('#tracked');
//code to respond to changes in the collections
this.listenTo(this.foods, 'add', this.rendertracked);
this.listenTo(this.foods, 'remove', this.rendertracked);
this.listenTo(this.breakfastlist, 'add', this.renderbreakfast);
this.listenTo(this.breakfastlist, 'remove', this.renderbreakfast);
this.listenTo(this.lunchlist, 'add', this.renderlunch);
this.listenTo(this.lunchlist, 'remove', this.renderlunch);
this.listenTo(this.dinnerlist, 'add', this.renderdinner);
this.listenTo(this.dinnerlist, 'remove', this.renderdinner);
this.listenTo(this.snacklist, 'add', this.rendersnack);
this.listenTo(this.snacklist, 'remove', this.rendersnack);
//code to not fire off a request right away
this.prepCollection = _.debounce(this.prepCollection, 1000);
},
addClicked: function(e) {
var $target = $(e.currentTarget).parent();
var $selected = $target.find('#mySelect').val();
var location = $target.attr('data-id');
//tracks the model selected in all of the collections
var currentFood = this.foods.get(location);
var currentBreakfast = this.breakfastlist.get(location);
var currentLunch = this.lunchlist.get(location);
var currentDinner = this.dinnerlist.get(location);
var currentSnack = this.snacklist.get(location);
//provides the html for the view
var currenthtml = currentFood.get('html');
switch ($selected) {
//case statements make sure model is added to the proper meal collection
//if elseif statements insure that no other collection except tracked has the same id-No duplicates
case 'Breakfast':
this.breakfastlist.create(currentFood);
if (currentLunch) {
this.lunchlist.remove(currentLunch);
} else if (currentDinner) {
this.dinnerlist.remove(currentDinner);
} else if (currentSnack) {
this.snacklist.remove(currentSnack);
}
break;
case 'Lunch':
this.lunchlist.create(currentFood)
if (currentBreakfast) {
this.breakfastlist.remove(currentBreakfast);
} else if (currentDinner) {
this.dinnerlist.remove(currentDinner);
} else if (currentSnack) {
this.snacklist.remove(currentSnack);
}
break;
case 'Dinner':
this.dinnerlist.create(currentFood);
if (currentBreakfast) {
this.breakfastlist.remove(currentBreakfast);
} else if (currentLunch) {
this.lunchlist.remove(currentLunch);
} else if (currentSnack) {
this.snacklist.remove(currentSnack);
}
break;
case 'Snack':
this.snacklist.create(currentFood);
if (currentBreakfast) {
this.breakfastlist.remove(currentBreakfast);
} else if (currentLunch) {
this.lunchlist.remove(currentLunch);
} else if (currentDinner) {
this.dinnerlist.remove(currentDinner);
}
break;
default:
alert("Error: try again");
}
},
removeClicked: function(e) {
var $target = $(e.currentTarget).parent();
var removeid = $target.attr('data-id');
//tracks the models in all of the collections
var modelRemoved = this.foods.get(removeid);
var breakfastRemoved = this.breakfastlist.get(removeid);
var lunchRemoved = this.lunchlist.get(removeid);
var dinnerRemoved = this.dinnerlist.get(removeid);
var snackRemoved = this.snacklist.get(removeid);
this.foods.remove(modelRemoved);
//remove the model if it exists in a collection
if (breakfastRemoved) {
this.breakfastlist.remove(breakfastRemoved);
} else if (lunchRemoved) {
this.lunchlist.remove(lunchRemoved);
} else if (dinnerRemoved) {
this.dinnerlist.remove(dinnerRemoved);
} else if (snackRemoved) {
this.snacklist.remove(snackRemoved);
}
},
prepCollection: function() {
var name = $('input').val();
var newUrl = "https://api.nutritionix.com/v1_1/search/" + name + "?results=0%3A20&cal_min=0&cal_max=50000&fields=item_name,brand_name,item_id,nf_calories&appId=26952a04&appKey=33b9262901d0068d4895736b5af19805";
//populate the collection with models and provide instruction html
if (name == "") {
this.$list.html("")
this.$instruct.html("")
} else {
this.$instruct.html("Click On A Food Item To Track It");
this.model.url = newUrl;
this.model.fetch({
success: function(response, xhr) {
console.log("Inside success");
console.log(response.toJSON());
},
error: function(errorResponse) {
console.log(errorResponse)
}
});
this.listenTo(this.model, 'sync', this.render);
}
},
track: function(e) {
var $target = $(e.currentTarget);
var item_name = $target.attr('data-name');
var brand_name = $target.attr('data-brand');
var calorieString = $target.attr('data-calories');
var calorieAmt = parseFloat(calorieString);
this.foodid = this.foodid + "1";
var chooseday = '<form>What meal was this part of?: <select id="mySelect"> <option value="Breakfast">Breakfast</option><option value="Lunch">Lunch</option><option value="Dinner">Dinner</option><option value="Snack">Snack</option></select></form><button id="add" type="button">Add To Meal</button><button id="remove" type="button">Remove From Tracked</button>';
var trackedhtml = '<li' + ' data-id=' + '"' + this.foodid + '"' + "<strong>" + item_name + '</strong>' + ' (' + brand_name + ')' + ' - ' + calorieAmt + ' Calories' + chooseday + '</li>'
this.foods.create({
id: this.foodid,
title: item_name,
brand: brand_name,
calories: calorieAmt,
html: trackedhtml
});
},
rendertracked: function() {
var total = 0;
var trackedhtml = '';
//resets the foodid variable when collection is empty to prevent long id names
if (this.foods.length == 0) {
this.foodid = ""
};
this.foods.each(function(food) {
trackedhtml = trackedhtml + food.get('html');
total += food.get('calories');
}, this)
this.$tracked.html(trackedhtml);
this.$total.html(total);
},
renderbreakfast: function() {
var total = 0;
var breakfasthtml = '';
this.breakfastlist.each(function(dish) {
breakfasthtml = breakfasthtml + dish.get('html');
total += dish.get('calories');
}, this)
$('#breakfast').html(breakfasthtml);
$('#totalbreak span').html(total);
},
renderlunch: function() {
var total = 0;
var lunchtml = '';
this.lunchlist.each(function(dish) {
lunchtml = lunchtml + dish.get('html');
total += dish.get('calories');
}, this)
$('#lunch').html(lunchtml);
$('#totalunch span').html(total);
},
renderdinner: function() {
var total = 0;
var dinnerhtml = '';
this.dinnerlist.each(function(dish) {
dinnerhtml = dinnerhtml + dish.get('html');
total += dish.get('calories');
}, this)
$('#dinner').html(dinnerhtml);
$('#totaldinner span').html(total);
},
rendersnack: function() {
var total = 0;
var snackhtml = '';
this.snacklist.each(function(dish) {
snackhtml = snackhtml + dish.get('html');
total += dish.get('calories');
}, this)
$('#snack').html(snackhtml);
$('#totalsnack span').html(total);
},
render: function() {
var terms = this.model;
var wordhtml = '';
terms.each(function(term) {
wordhtml = wordhtml + '<li' + ' data-name=' + '"' + term.get('fields')['item_name'] + '"' + ' data-brand=' + '"' + term.get('fields')['brand_name'] + '"' + ' data-calories=' + '"' + term.get('fields')['nf_calories'] + '"' + '>' + "<strong>" + term.get('fields')["item_name"] + '</strong>' + ' (' + term.get('fields')["brand_name"] + ')' + ' - ' + term.get('fields')["nf_calories"] + ' Calories' + '</li>'
}, this);
this.$list.html(wordhtml);
}
});
var app = new App();
});
这是我的HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Food Guide App</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="text-center bg-black">
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1>Interactive Food Guide</h1>
</div>
</div>
</div>
</div>
<div class="bg-blue">
<div class="container">
<div class="row">
<div class="col-sm-6">
<h2>Food Search</h2>
<img class="img-responsive" src="img/my-food-guide-plate.jpg" alt="food plate photo">
<a name="foodsearch"></a>
<h4>Look up food here:</h4>
<input type="text" id="searchBox"> <br/><br/>
<p id="instruct"></p>
<ul class="spacefood" id="listing"></ul>
<a href="#foodtrack">Go to food tracking</a>
<p>
Go to:
<a href="#breakfastrack">Breakfast</a>
<a href="#lunchtrack">Lunch</a>
<a href="#dinnertrack">Dinner</a>
<a href="#snacktrack">Snack</a>
</p>
</div>
<div class="col-sm-6 top-space bottom-space">
<img class="img-responsive" src="img/foods.jpg" alt="foods">
<a name="foodtrack"></a>
<h2>Foods Tracked</h2>
<ul class="top-space spacetracked" id="tracked"></ul>
<p id="total"><strong> total calories:</strong> <span>0</span></p>
<a href="#foodsearch">Go to food search</a>
<p>
Go to:
<a href="#breakfastrack">Breakfast</a>
<a href="#lunchtrack">Lunch</a>
<a href="#dinnertrack">Dinner</a>
<a href="#snacktrack">Snack</a>
</p>
</div>
</div>
</div>
</div>
<div class="bg-white">
<div class="container">
<div class="row">
<div class="col-sm-6">
<a name="breakfastrack"></a>
<h1>Breakfast</h1>
<ul class="spacetracked" id="breakfast"></ul>
<p id="totalbreak"><strong> total calories:</strong> <span>0</span></p>
<a href="#foodsearch">Return to food search</a>
<p><a href="#foodtrack">Return to food tracking</a></p>
<p>
Go to:
<a href="#breakfastrack">Breakfast</a>
<a href="#lunchtrack">Lunch</a>
<a href="#dinnertrack">Dinner</a>
<a href="#snacktrack">Snack</a>
</p>
</div>
<div class="col-sm-6">
<img class="img-responsive" src="img/breakfast-meal.jpg" alt="breakfast plate photo">
</div>
</div>
</div>
</div>
<div class="bg-blue">
<div class="container">
<div class="row">
<div class="col-sm-6">
<a name="lunchtrack"></a>
<h1>Lunch</h1>
<ul class="spacetracked" id="lunch"></ul>
<p id="totalunch"><strong> total calories:</strong> <span>0</span></p>
<a href="#foodsearch">Return to food search</a>
<p><a href="#foodtrack">Return to food tracking</a></p>
<p>
Go to:
<a href="#breakfastrack">Breakfast</a>
<a href="#lunchtrack">Lunch</a>
<a href="#dinnertrack">Dinner</a>
<a href="#snacktrack">Snack</a>
</p>
</div>
<div class="col-sm-6">
<img class="img-responsive" src="img/lunch-meal.jpg" alt="lunch plate photo">
</div>
</div>
</div>
</div>
<div class="bg-white">
<div class="container">
<div class="row">
<div class="col-sm-6">
<a name="dinnertrack"></a>
<h1>Dinner</h1>
<ul class="spacetracked" id="dinner"></ul>
<p id="totaldinner"><strong> total calories:</strong> <span>0</span></p>
<a href="#foodsearch">Return to food search</a>
<p><a href="#foodtrack">Return to food tracking</a></p>
<p>
Go to:
<a href="#breakfastrack">Breakfast</a>
<a href="#lunchtrack">Lunch</a>
<a href="#dinnertrack">Dinner</a>
<a href="#snacktrack">Snack</a>
</p>
</div>
<div class="col-sm-6">
<img class="img-responsive" src="img/dinner-meal.jpg" alt="dinner plate photo">
</div>
</div>
</div>
</div>
<div class="bg-blue">
<div class="container">
<div class="row">
<div class="col-sm-6">
<a name="snacktrack"></a>
<h1>Snack</h1>
<ul class="spacetracked" id="snack"></ul>
<p id="totalsnack"><strong> total calories:</strong> <span>0</span></p>
<a href="#foodsearch">Return to food search</a>
<p><a href="#foodtrack">Return to food tracking</a></p>
<p>
Go to:
<a href="#breakfastrack">Breakfast</a>
<a href="#lunchtrack">Lunch</a>
<a href="#dinnertrack">Dinner</a>
<a href="#snacktrack">Snack</a>
</p>
</div>
<div class="col-sm-6">
<img class="img-responsive" src="img/snack-meal.jpg" alt="snack plate photo">
</div>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Backbone and Underscore -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone-min.js"></script>
<!-- apps functionality -->
<script src="js/app.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<!-- Firebase -->
<script src="https://cdn.firebase.com/js/client/2.2.9/firebase.js"></script>
<!-- BackboneFire -->
<script src="https://cdn.firebase.com/libs/backbonefire/0.5.1/backbonefire.min.js"></script>
</body>
</html>
答案 0 :(得分:1)
基本上,您不必在index.html中拥有指向app.js文件的链接,而是必须在index.html中以正确的顺序包含每个文件。您可以像这样构建文件夹:
span
在/js
/models
/collections
/views
文件夹中,您可以将您的馆藏,模型放在/collections
文件夹中,依此类推。可以将集合称为AllFoodsCollection.js和BreakfastCollection.js。然后你在index.html中引用它们。记得让你按正确的顺序分数。
/models
如果你使用像Gulp或Grunt这样的构建系统,它可以帮到你很多。使用Google's Web Starter Kit可以轻松开始。
看起来您还可以阅读一些关于如何构建骨干代码的正确教程。例如,当您要更改的是url属性时,您真的不需要所有这些集合。你可以有一个集合:
<script src="js/models/FoodModel.js"></script>
<script src="js/collections/AllFoodsCollection.js"></script>
<script src="js/collections/BreakfastCollection.js"></script>
然后像这样实例化一个集合:
var FoodCollection = Backbone.Firebase.Collection.extend({
model: Food,
collectionType: '',
url: function() {
"https://blinding-torch-8751.firebaseio.com/" + this.collectionType;
}
});
有一本关于如何使用主干的好书,有很多关于如何构建代码的提示,在这里:http://addyosmani.github.io/backbone-fundamentals/。
健康追踪器应用程序祝你好运:)。