At the Forge - Backbone.js
Of course, most people have to schedule more than one appointment, which means that this example program needs to keep track of more than one at a time. Now, you normally might assume that you simply could store more than one appointment in a JavaScript array. But, in the world of Backbone.js, you actually use a special kind of object, known as a collection, to store appointments.
Why a collection and not simply an array? Mostly because it works together with other items in Backbone.js. For example, you can set things such that whenever you add or remove an element to your collection, it automatically will invoke another method. For another, collection objects incorporate the Underscore library for JavaScript, which defines a number of methods from functional programming, such as map and pluck, so retrieving information from your collection is quite straightforward.
Just as you defined a model by extending Backbone.Model, you define a collection by extending Backbone.Collection:
Appointments = Backbone.Collection.extend({
});
Any attributes that you define on the collection are then available, as data or functions, on collection objects of this type. In this particular case, I defined two different attributes, the initialize constructor and the update_appointment_counter method:
Appointments = Backbone.Collection.extend({
update_appointment_counter: function() {
$("#number-of-appointments").html(this.length);
},
initialize: function(models, options) {
$("#number-of-appointments").html(this.length);
this.bind("add", options.view.add_appointment_row);
this.bind("add", this.update_appointment_counter);
}
});
In this case, the constructor uses jQuery to initialize the appointment length counter (to zero, given that the collection is only now being initialized) and then adds two handlers to the “add” event. Each time you add a new appointment to this collection, two different functions will fire. One of them (options.view.add_appointment_row) will add a new row to the HTML table containing a list of appointments, and the other (this.update_appointment_counter) updates the counter. As you can see, the functions can be defined in a variety of places; it probably would have made more sense to put both of these methods on the view.
Experienced JavaScript programmers know what “this” is; thus, this.update_appointment_counter makes sense. But, what is options.view? Well, it might help to see how you create your collection, inside the view constructor:
initialize: function() {
this.appointments = new Appointments(null, {view:this});
},
Basically, you're saying that the appointments attribute for the view is an Appointments collection, starting with no data. Passing a second parameter allows you to set one or more options in a JavaScript object, which is then available as “options”. Because the view passes itself (!) as the “view” option when creating the collection, you then can access the view from within the collection as options.view.
The upshot is that your view, thus, has access to your collection (as this.appointments), and your collection has access to our view (as options.view). This sort of simple, two-way communication is typical for Backbone.js, which tries to make things as simple and short as possible.
The code doesn't include a controller. That's because controllers are necessary only if you want to provide a number of different URLs—well, fragments at the end of a URL—that invoke different methods. For now, you can do without it, but a larger application certainly will require it.
As always in the MVC paradigm, the view is where things are displayed to (and interact with) the end user. In the Rails world, a view is almost always rendered by the controller; your application doesn't need to create it explicitly. In the Backbone.js world, a view is just another object that can be created, often by a model, and which has many controller-like functions. You create it, as you might expect, with:
AppView = Backbone.View.extend({
});
So, you can think of Backbone.js views as fragments of HTML that are added to the current page, plus some of the functionality that you might associate with a controller. Each view is associated with a DOM element. By default, it's a regular “div” element, but you either can set it in one place (using the “el” attribute), or you can set it using a combination of the “tagName”, “className” and “id” attributes as well.
As with models and collections, you can use the “initialize” constructor to set up one or more objects. In the case of this example application, you'll initialize your Appointments collection without any element members, as you saw above when I discussed that collection.
You also will define an event handler, such that clicking on the “add-appointment” button will do so:
events: {
"click #add-appointment": "add_appointment"
},
When you click on the button, the following code is executed:
add_appointment: function() {
var person = $("#new-appointment td input[name=person]").val();
var meeting_at = $("#new-appointment td
↪input[name=meeting_at]").val();
var note = $("#new-appointment td input[name=note]").val();
this.appointments.add({person: person, meeting_at: meeting_at,
↪note: note});
},
In other words, when you click on the “add-appointment” button, the “click” event handler executes the add_appointment function. This function grabs the values from the little form and uses those values to instantiate a new appointment, adding it to the collection of appointments.
But, you also have event handlers running on the collection! The first handler updates the appointment counter, and the second adds a new row to the table of appointments. It adds the row by cheating a little bit. Although it would have been more elegant to have a second view with an element of “tr” that would add a new row, I decided to mimic some of the on-line tutorials I've seen, adding a new row in a slightly simpler way—namely, an ugly text string.
If I weren't interested in creating an entirely new view, I could have used the “template” function that Backbone.js inherits from underscore.js, giving me ERb-like templates that can be filled in more nicely. Something else that I could have done is break this application into smaller pieces. Although it's nice to have everything in a single file when working on something small, a larger Backbone.js application could well be put into multiple files, with each file defining a different object. Developers experienced with any modern server-side MVC framework, such as Rails or Django, will understand the advantages of putting things into separate files.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
Web Development News
Developer Poll
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Home, My Backup Data Center
- A Topic for Discussion - Open Source Feature-Richness?
- What's the tweeting protocol?
- Dart: a New Web Programming Experience
- Developer Poll
- Trying to Tame the Tablet








1 hour 18 min ago
3 hours 50 min ago
5 hours 8 min ago
5 hours 43 min ago
6 hours 5 min ago
10 hours 54 min ago
11 hours 40 min ago
13 hours 14 min ago
14 hours 51 min ago
16 hours 49 min ago