Backbone was created by Jeremy Ashkenas in October 13, 2010. The creation of Backbone stems from his concerns of how javascript is structured.
What he means by that is that when you create applications that incorporate javascript, it can become hectic to keep all the data organized together, with HTML properties, the javascript code and complexity of it can lead to utter confusion and disorder between all these elements.
Throughout the semester, we’ve been learning javascript and how we can make our web pages more dynamic, to have more content in it, and to ensure website applications that aren’t as plain or basic. However, as we continue the course, we realize that with more functionality to our sites leads to more code, which can increase the chances of disorganization, code bundled here and there, increasing the lack of a structure. Backbone is relevant/important to this class because it is a piece of technology/ a framework that aids in the application of javascript. This framework is one of many that users can choose from. They have the ability to install any framework and to have it work for their needs. In this tutorial, I will show you some steps on how Backbone works.
Backbone provides organization , a more efficient, robust, and precise approach towards javascript.
How does Backbone provide this? It's really simple, they change the way of manipulating data using more organized ways, such as Models and Views !
You might be thinking, "How does this relate to the concept of MVC?" it can be confusing to understand. The best way to interpret how Backbone approaches this concept, is that it primarily focuses on MV. The explanation for Controller is that it is integrated inside of the Views.
You are going to need Three things...
If you click those links, they'll take you to their respective site to download.
When you reach the website for Backbone and Underscore, you can right-click the download and save it as a .js file. It's that easy!
https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
Models are like classes, if you want to create a model, you have to do declare a new variable, with the name as your model, and extend backbone to fiddle with its properties.
For example, let's say you want to create a model for something. How would you go about that? First, think of what you want to create. For my example, I'll pretend I'm making a game about fighting, and my fighting game needs weapons, so I'll create a Melee weapon class, since it can contain a lot of attributes.
Once you figure out what you want, you create it by extending the model that comes from backbones core. Like this!
var MeleeWeapon = new Backbone.Model.extend({ }); //To create a MeleeWeapon, do this below var BaseballBat = new BaseballBat();
Cool, now I have a model for melee weapons for my game! What now? It's a melee weapon model, but there's nothing in it. To fix that, let's try to give it some properties to build up this model. To do that, we have to work more under the extend property. Here's a simple property we can start off with, called Initialize , and I want so that everytime I create a melee weapon , it will tell the console that I just created a melee weapon.
var MeleeWeapon = Backbone.Model.extend({ initialize: function(){ console.log("Melee weapon has been created!"); alert("Melee weapon has been created!"); } }); //To create a MeleeWeapon, do this below var BaseballBat = new BaseballBat();
Now, if we try to run this code, everytime we create a Melee weapon, it will tell the console that we created a melee weapon model and alert the screen! Test it out with the button
You can do much more aside from initialize, there's many other properties you can change around. Before we start more on that, let's see how we can upgrade our melee weapon
Note that you can also extend the model later on as well if you need to. Not everything has to be extended in that bar of code, you can extend it later on just by referring to that model and extending it again.
I'm still going to work with a baseball bat as a melee weapon. How else can I give my melee weapon properties? Let's think: Baseball Bats are a "blunt" weapon, as opposed to something sharp like knives, Baseball bats could also have a quality, like being super weak or super strong like metal. To give a class some sort of property, you don't have to make constructors first like how you would in javascript, you can make it on the spot.
//To create a MeleeWeapon with a meleetype, and the quality, do this below. You have to add brackets between the parentheses if you want to create properties for it. var BaseballBat = new BaseballBat({ meleetype: "Sharp", quality: "High" });
Great! My bat has a melee type and quality, but I also just realized my Baseball Bat is a blunt weapon, and I accidentally said it was sharp! but how do I know it's really there? We can use the "get" function that all models have when we want to access one of their properties. And to change a property of our model, we can use "Set "Look at the code below for a demonstration on how to get properties.
//To create a MeleeWeapon with a meleetype, and the quality, do this below. You have to add brackets between the parentheses if you want to create properties for it. var BaseballBat = new BaseballBat({ meleetype: "Sharp", quality: "High" }); alert("This is my BaseBall Bat, the type is: " + BaseballBat.get("meleetype") + " AND it's made out of metal, so the quality is " + Baseballbat.get("quality")); BaseballBat.set("quality", "Blunt"); alert("My baseball bat isn't sharp! It should be " + BaseballBat.get("meleetype"));
Now you know how to give it properties. But let's expand on our code a bit more. Let's see how we can make this better, I'm going to write a list of what should be done to expand on this model
Let's test this out!
var MeleeWeapon = Backbone.Model.extend({ initialize: function () { console.log("Melee weapon has been created!"); //alert("Melee weapon has been created!"); }, defaults: { name: "Empty Weapon", meleetype: "Tickles like a feather", quality: "Low", material: "Paper", meleeweaponImage: "https://i5.walmartimages.com/asr/d0dd7b35-43dd-4cd0-ba91-9c96ac815112.fbfd9f47a896d3f3c239d4a936b0205c.jpeg" }, toString: function () { return "My weapon: " + this.get("name") + " the melee type: " + this.get("meleetype") + ", the quality is " + this.get("quality") + " and the material is made out of " + this.get("material") + " Here's what it looks like!" + this.get("meleeweaponImage"); } }) var BaseballBat = new MeleeWeapon({ name: "The coolest weapon ever!", meleetype: "Sharp", quality: "High" }); alert(BaseballBat.toString());
And that is basically how models work in Backbone. We can use models to create their own properties, methods, what happens when one is initialized, and even more!
So you have a model now, it has properties, default values, and a toString method. I want to create a way for users to see my weapon though. To do that, we have to allow our melee weapon model to be viewed, and to do that, we create something that Backbone has also incorporated for us: Views!
A view is a way to see your data. Just like how you can customize your data, you can customize how they look to the user.
So, how would one begin by making a view? It's easy, it's just like creating a model!
var WeaponShowcase = Backbone.View.extend({ });
Just like creating models, you can create views the same way. They just serve different purposes (Models are data and Views are a way to present data.
Just like what we do with models, we can create properties for our views just like initialize, and creating its own methods/functions.
However there is one big difference between Views and models, which is the Render function. Views have the ability to render their content/data, which is how we see it. They respond to DOM events (Such as Clicks events)
Below is an example of our previous View, but with added properties. Render allows us to view the content.
var WeaponShowcase = Backbone.View.extend({ initialize: function () { console.log("Showcase for our weapon"); }, render: function () { this.$el.html("Hey, this is my weapon!" + this.model.get("name")); return this; } }); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var BaseBallView = new WeaponShowcase({ el: "#ViewContainerTest", model: BaseballBat }); BaseBallView.render();
So we created a view, and with that view, created a simple render function and a small initialization function as well. In the render function, you might be confused as to what $el is. $el is the element that is used as the view reference. See how when we created our view, we gave it some properties? el specified what element we're going to focus our view on. In that case, i focused on a div with the ID called ViewContainerTest', and I had to base our view on the model BaseBallBat.
NOTE: Having a model is completely optional for a view, but since my View render takes in a models name, I had to specify it, but if you create a view render that doesn't use any model attributes, that is okay!
Collections are almost like the equivalent of arrays and other objects that hold in more than one data. For example, in my previous model and view which was about melee weapons, how else would I go about creating a bunch of baseball bats, and/or a bunch of other types of weapons?
This here is a BAD example of what you shouldn't do. This example will demonstrate multiple melee weapons being rendered.
WeaponShowcase = Backbone.View.extend({ render: function () { this.$el.append("Hey, this is my weapon: " + this.model.get("name") + " "); return this; } }); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var BaseBallView = new WeaponShowcase({ el: "#BadModelViewExample", model: BaseballBat }); var Pickaxe = new MeleeWeapon({ name: "Tony's Pickaxe", meleetype: "Sharp", quality: "Poor" }); var PickaxeView = new WeaponShowcase({ el: "#BadModelViewExample", model: Pickaxe }); var Lightsaber = new MeleeWeapon({ name: "Obi-wans Saber", meleetype: "Laser", quality: "High" }); var LightsaberView = new WeaponShowcase({ el: "#BadModelViewExample", model: Lightsaber }); BaseBallView.render(); PickaxeView.render(); LightsaberView.render();
Note that we changed one small part in the render function, which is append, since we want the el that the view is assigned to, to not clear anything in the assigned div. We give it the append option instead.
It might not seem bad, since we're just rendering 3 unique views. But this gets very tedious when you have to create multiple views and multiple models. Also, if you spam the button, it keeps appending. What if I just want this to append just once with all my views?
To fix this bad practice, we use collections. Just like creating a new model, or creating a new view, we do the same for a collection
This example below is a creation of a new collection and adding models to our collection.
var MeleeWeaponCollection = Backbone.Collection.extend({ initialize: function () { console.log("Melee weapon Collection created"); } var CollectionExample = new MeleeWeaponCollection(); }); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var Pickaxe = new MeleeWeapon({ name: "Tony's Pickaxe", meleetype: "Sharp", quality: "Poor" }); var Lightsaber = new MeleeWeapon({ name: "Obi-wans Saber", meleetype: "Laser", quality: "High" }); ExampleCollection.add(BaseballBat); ExampleCollection.add(Pickaxe); ExampleCollection.add(Lightsaber);
Now we have a simple collection consisting of 3 models.
Just like models though, they're just purely data. Like an array holding objects, Backbone has Collections holding Models. AND Just like Models, Collections need views so that we can render out our collection to be seen on the page.
The next example will be keeping the same Model and Collection as previous, and will add a new view to render our collection.
var ExampleCollection = new MeleeWeaponCollection(); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var Pickaxe = new MeleeWeapon({ name: "Tony's Pickaxe", meleetype: "Sharp", quality: "Poor" }); var Lightsaber = new MeleeWeapon({ name: "Obi-wans Saber", meleetype: "Laser", quality: "High" }); ExampleCollection.add(BaseballBat); ExampleCollection.add(Pickaxe); ExampleCollection.add(Lightsaber); var ExampleCollectionView = Backbone.View.extend({ //Our view render: function () { this.$el.empty(); //1 var self = this; //2 this.model.each(function (Weapon) { //3 var WeaponView = new WeaponShowcase({ model: Weapon }); //4 self.$el.append(WeaponView.render().$el); //5 }); } }); var myCollectionView = new ExampleCollectionView({ el: "#YourSpecificDivHere", model: ExampleCollection }); myCollectionView.render();
ExampleCollectionView is a new view, we specified what div it should go to, and gave it a model to base it's data from, which is from the ExampleCollection collection.
ExampleCollectionView only has one property: it's render function. I named each line of code a given number to explain. Inside the render function has //1, is where we empty out the element (This prevents the element from duplicating constantly since we are appending our view).
//2, We make a variable called self, referencing this in relation to
//3, Is our for-each loop equivalent
//4, Inside our for-each loop, I want to take each MeleeWeapon in that collection and assign it a view.
//5, After assigning every model a view, I append that rendered view onto our specified element. As each model is looped, each one gets a view, and each view gets rendered onto the HTML element. Note that I called it Weapon in the for-each loop and not MeleeWeapon, you can call it anything you want, Regardless of what name, that name is always a reference to the current object in that loop.
And All we do afterwards is we create a new ExampleCollectionView, assign it an element to display, and assign it a model for the view to render out it's data, which is the collection ExampleCollection.
You can look for specific items in collections (Like arrays!). With collections, you can search a collection in some ways. Here are some examples of searching through collections. This code will reference the previous MeleeWeapon model and collection.
var ExampleCollection = new MeleeWeaponCollection(); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var Pickaxe = new MeleeWeapon({ name: "Tony's Pickaxe", meleetype: "Sharp", quality: "Poor" }); var Lightsaber = new MeleeWeapon({ name: "Obi-wans Saber", meleetype: "Laser", quality: "High" }); ExampleCollection.add(BaseballBat); //Add all these models to a collection ExampleCollection.add(Pickaxe); ExampleCollection.add(Lightsaber); var SharpWeapons = ExampleCollection.where({meleetype: "Sharp"}); var myFirstSharpWeapon = ExampleCollection.findWhere({ meleetype: "Sharp" }); console.log(SharpWeapons); console.log(myFirstSharpWeapon) //Check the console for both the results
This example shows 2 ways of finding collections: where and findWhere.
The main difference between the two is that where finds the First instance of what one is looking for, whereas findWhere finds all models in a collection that fit the users criteria.
Templates are an easy way for views to render out content. It's a way to make a display without doing it in the view. The only thing you need to do in a view is to assign it a template, and it does the work for you.
Below is an example of a template being applied for a view. The code is split into two parts: The first part being the template, the second being the code that uses the template.
<''script type="text/template" id="TutorialTemplate"> <%= name %> //line break <%= meleetype %> //line break <%= quality %> //line break ''script>
The code below uses the template above.
WeaponShowcase = Backbone.View.extend({ template: _.template($("#TutorialTemplate").html()), render: function () { this.$el.html(this.template(this.model.toJSON())); } }); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var myView = new WeaponShowcase({ el: "#TemplateExample", model: BaseballBat }); myView.render();
Below is code that works for templates on a Collection, rather than one view for one model. We're working with the previous MeleeWeapon model, view, and collection, but extending it on some properties.
WeaponShowcase = Backbone.View.extend({ template: _.template($("#TutorialTemplate").html()), render: function () { var test = _.template($("#TutorialTemplate").html(), this.model.toJSON()); var myTemplateinfo = test(this.model.toJSON()); //this.$el.html(myTemplateinfo); this.$el.html(this.template(this.model.toJSON())); return this; } }); var ExampleCollection = new MeleeWeaponCollection(); var BaseballBat = new MeleeWeapon({ name: "BaseBall Bat!", meleetype: "Sharp", quality: "High" }); var Pickaxe = new MeleeWeapon({ name: "Tony's Pickaxe", meleetype: "Sharp", quality: "Poor" }); var Lightsaber = new MeleeWeapon({ name: "Obi-wans Saber", meleetype: "Laser", quality: "High" }); //var LightsaberView = new WeaponShowcase({ el: "#BadModelViewExample", model: Lightsaber }); ExampleCollection.add(BaseballBat); ExampleCollection.add(Pickaxe); ExampleCollection.add(Lightsaber); var ExampleCollectionView = Backbone.View.extend({ //Our view render: function () { this.$el.empty(); var self = this; this.model.each(function (Weapon) { var WeaponView = new WeaponShowcase({ model: Weapon }); self.$el.append(WeaponView.render().el); }); } }); var myCollectionView = new ExampleCollectionView({ el: "#TemplateCollection", model: ExampleCollection }); myCollectionView.render();
The code works similar to the last one, except that for our collection, we have to create a render function where for each weapon/model, we assign it a new view, render that view, and append it to our element.
A super big important detail is that for this to work, you have to make sure the Singular View for a weapon has their render function return this. This is because when our Collection view renders multiple models, it needs that return statement to grab the current models rendered content, allowing it to be appended.
With that, that should be enough information to start creating your own data, changing around data, its properties, views, collections, and templates. Good luck!
Here are some references to use if looking to use backbone. I think looking at youtube tutorials is much better than the backbone website itself.
https://backbonejs.org/ https://www.youtube.com/watch?v=4t0n5k0X7ow (This consists of some youtube videos from the same person teaching it) https://www.youtube.com/watch?v=HOAU-nfy5Sc