00:01Alright. So my name's Allan Laframboise. Welcome to the summit. I hope you guys are having a good time.
00:07I'm really actually excited to introduce a couple of my friends up here...
00:16And, so Brian and Mike from DTS Agile will be doing this for about 30 minutes or so...
00:23...and then we'll wrap up with a few questions near the end, and it's up to these guys how they want to roll with the show.
00:29So I'm just going to pass it on to them, so here we go.
00:37So as I get started today, I apologize for the screen.
00:41If any of you are in here for our How to Present presentation, I said, Know Your Venue...
00:47...and we didn't realize until about halfway through the previous talk that we were cutting our own slides off.
00:52The other option was that everything for the demo in the web browser was really, really small.
00:57So we've erred on the side of bigifying things.
01:01I'm going to talk about backbone JS framework today, and I want to start with just a little...
01:09...putting our fingers on the pulse of the industry type thing.
01:12And this is from July 2011.
01:16I was out on the identity mine site reading through a blog post, and this was in the comments.
01:22Fellow identified only as Carlos. I'd call him out with more contact information, but that's all he listed up there.
01:30And he was basically making the point very succinctly that...
01:34...no matter how much you hate working without a WYSIWYG designer and...
01:37...no matter how much you loathe working without, you know, full intellisense in your IDE...
01:52It's the premier way that software is made now.
01:57Something a little more recent, from just yesterday.
02:00This was actually on the front page of the New York Times.
02:03We were able to find it online where people like stockbrokers and money managers and doctors and lawyers...
02:18...and Python is also used as an example in this article.
02:22And it's really reinforcing this quote from the folks at Carsonified that mobile is a very, very big deal.
02:31Millions and millions of devices out in peoples' hands already. Millions more will be activated this year.
02:40And that presents a challenge for us as developers because we love our devices.
02:47I don't have just my phone, you know, I've got a Mac and a tablet and a phone and then the old phone that's in the drawer...
02:55...and people accumulate these devices, and they expect to be able to consume your information anywhere.
03:02We've gone far past the point where I go to the Internet at my home before I leave to get all the information I need for the day.
03:12I'll be in the grocery store and whip out my phone and expect to consume something that I read earlier.
03:19And for developers, that's a real problem, because we have to provide information and application functionality...
03:29...that runs on all these devices.
03:32And so, our task is to say, How do we build something that runs on a whole bunch of different devices?
03:39How do we support that in an easy way that doesn't involve us maintaining 18 or 20 different code bases?
03:48Flex is not going to do that for us.
03:50Adobe has sort of kicked that out the door over to the Apache project and killed that.
03:57Silverlight isn't going to do that for us.
04:00You know, we all are reading the flip-flopping press releases coming out of Microsoft about Windows 8 and in Metro mode.
04:10Read a very interesting thing. Metro mode is the way it will ship for tablets, and there are no plug-ins allowed in Metro mode.
04:19So Silverlight will run on, it looks like, exactly zero mobile devices.
04:25So the future really is in the browser, and reinforcing that is the fact that these four technology companies...
04:33...who ordinarily would walk across the street to sue each other over a patent infringement or punch each other in the nose...
04:41...all agree, to some extent, that HTML5 is the way of the future.
04:53It's gone from being this thing that we do stupid tricks with to make things flash on websites...
05:01...to becoming a very, very important part of our daily lives as software developers.
05:07And if we go back in time just a little bit to just after Al Gore invented the Internet...
05:20...Welcome to my web page.
05:22Apparently, someone even thought it was a good idea to worship Dolph Lundgren using this technology...
05:27...and really, you know, 15 years ago Brendan Eich must have been ready to put a gun to his own head and say...
05:33...What have I created?
05:47And so it's being used now to provide the same interactivity...
05:53...that you would have expected from a flash application just a few years ago.
06:04Creating responsive, fluid, maintainable interfaces very, very quickly from scratch is time consuming and code intensive.
06:14Fortunately, there are a whole bunch of bright people out there who looked at this problem and said...
06:19...Hey, what we need is a framework.
06:21Now, just like has happened in the .NET world and the Java world and everything else...
06:26...we have a proliferation of frameworks.
06:28This is a simple Google query here, 20 Java frameworks worth checking out.
06:34Don't really understand that write-up, because if you can't find what you want after looking at three...
06:38...you're not going to find it after 20.
06:49And so what we have come to is a place where we have lots and lots of very rich, very good frameworks...
06:58...that make development much easier and impart interactivity by virtue of what's been written.
07:04jQuery and Dojo are probably the most familiar to all of us in here, other things out there that are less widely used.
07:13The issue with most of those frameworks, and there are exceptions, but the issue with most of them is...
07:19...they don't say anything about structure or modularity.
07:23How do we organize our code? What files do I put them in?
07:26How do I load those files into the browser so I'm not tanking the thing every time someone asks for a bunch of information?
07:34And that all has a long-term effect on us as developers, because it impacts the maintainability and the extensibility of our applications.
07:44Now, because there is enough suck in my own history that I don't need to pick on anyone else...
07:50...this is a project we did for the State of Utah, and because of the way we elected to build the interface...
08:04And it's organized into all these nice folders you see over here...
08:09...which is all good things until you understand that at different points on the project...
08:13...we had three different developers writing code in different ways and packing these folders filled with all kinds of goodness...
08:21...that Steve Gurley back here in the middle of the room has to maintain now.
08:28The other issue with a lot of the frameworks that have come out so far is...
08:45And so there haven't been any real hard and fast recommendations or efforts put into making this unit testable in any easy way.
08:54Well, enter our friend, Jeremy Ashkenas who we should all know and love.
08:59Now Jeremy is a pretty busy boy.
09:02He's the guy that wrote CoffeeScript.
09:06He's the guy that wrote DocumentCloud.
09:09And did I mention, he also has a full-time job with the interactive news group at the New York Times.
09:16He also gave us what I will talk about today, Backbone.js framework.
09:21And this is actually something that came out of that DocumentCloud project that they used to modularize their code...
09:28...and he open-sourced it.
09:31And what Backbone.js is, is essentially a framework that gives structure and modularity to your code by providing you with views...
09:42...and those views have key value binding to DOM elements and custom events that you respond to, oh, excuse me...
09:48...models, I'm sorry, collections of models that have an API of all the innumerable functions...
09:57...that you would expect on a collection.
10:00And then views that handle events on models and connect all your things together with REST and JSON.
10:08Very, very good things.
10:11What Backbone.js is not is, it's not a DOM manipulation tool.
10:16It's not another jQuery for you to do fancy, shiny things that the user sees.
10:22You're still going to use jQuery or Dojo or both inside your views to get SOM elements and put data in and take data out...
10:31...and make things look pretty.
10:32But that's not what this framework is for.
10:36I'll also mention, it was in our abstract that I would talk about MVC, and I did a lot more reading on this...
10:41...and there's some debate, is Backbone fish or fowl? Is it truly a model-view-controller framework?
10:49I don't know.
10:51The controller logic that you would typically see in an MVC framework sits in the view in this case...
10:59...and some people have said, No, it's actually MVVM.
11:03We're saying, Who cares?
11:06This is good stuff. It's helpful to us as developers, so we're going to use it.
11:11So the big ideas, how does Backbone lay out?
11:14Well, first, we have models, views, and collections, as I mentioned.
11:19And those models typically hold all of your interactive data, so data in the database that you want to display to the user...
11:26...data that's generated in the UI that drives other UI interaction events.
11:31Those things go into models, also any logic that operates when those models change...
11:38...and to implement those, you're essentially writing a function that extends Backbone.model.
11:45Next in line is Backbone views.
11:49This where all the logical things that happen in a UI are placed, and these are typically broken out into chunks.
11:57So if you have a map and a panel and a grid below it, each one of those things might be a view...
12:10Collections hold sets of models.
12:13And you'll see there are a variety of ways you can break your data up...
12:16...depending on how you want to drive the user interaction.
12:21They hold your models, and they have innumerable functions, other events.
12:25The kind of nice thing about collections in Backbone is, they will actually bubble out events that occur on individual models.
12:32So if you have 10 rows of data and one of those rows changes, the collection itself will bubble that out for you...
12:40...and tell you which model changed.
12:43There are some other nice things in there that I'm not going to cover in depth.
12:47We'll just go over.
12:48There's also a router inside Backbone.js, and when all this stuff is going on in the client, what happens when you hit the Back button?
12:58And so the router can help you manage history, and it will also help you construct these restful URLs...
13:05...that manage the states of your page as the user is moving through your application.
13:11For unit testing, we used QUnit and Sinon.js.
13:22Jasmine is popular in the Ruby realm for unit testing.
13:26We use QUnit since we were...just because it suited what we were doing.
13:33The other thing that we've rolled in here, and Mike'll cover it a little more in the demos is view templating.
13:40If you're going to render the same information over and over and over again, like rendering rows in a table in HTML...
13:48...it gets pretty cumbersome to write repetitive code to do that.
13:52And what ICanHaz does is it wraps the Mustache libraries and allows you to establish view templates...
14:03...that allow you to insert repetitive code without writing that code over and over and over again.
14:09And we can talk a little bit about that syntax later.
14:14Before I turn it over the Mike to talk a little bit, I did want to mention Rene is sitting here in the second row.
14:34...but he's got a good explanation, point by point, out on his site with lots of good links.
14:41He links over to GitHub repository of a whole bunch of examples doing modularization with this API.
15:00I'm going to turn it over to Mike Juniper, and he's going to walk through a couple of simple examples...
15:05...and then we're going to show sort of an industrial-scale site that we built using this technology.
15:23That's what I'm going to talk about.
15:26So I like to start small.
15:29So...okay so...oops...I'm not a Mac guy, so...
15:42This is just an Esri sample, a super simple one, just a map.
15:46This little bit of UI down here at the bottom just tells you what the current extent is of the map whenever you change it.
15:57See. Super simple.
16:06Here it is. This is the same app, just reimplemented with Backbone.
16:13Looks and acts basically the same way.
16:19Okay, so how do we build that?
16:24Alright. Yeah, not a Mac guy. There we go.
16:33Okay, so the first hurdle that I ran into was, what the heck is the map?
16:40Is it a view? Is it a model? Is it both? Is it neither?
16:44And, the answer that I came up with is, it depends.
16:49You know, it depends on the specific requirements of the application that you're building.
16:54And I think to answer the question for the particular app you're building, it helps to keep first principles in mind.
17:01What's Backbone about fundamentally?
17:02And I think fundamentally it's about views, which are just a logical bit of UI reacting to changes on models.
17:10Simple as that.
17:11So when you look at it that way, that little gray bar at the bottom that shows you the current extent, clearly that's a view.
17:18We want it to react to changes on the map.
17:21Okay. Boom. The map is a model.
17:24So this is our map model.
17:31We, you know, to create a Backbone class, you expend Backbone, in this case, model.
17:37That's that first line.
17:39Second line is initialized. That's Backbone speak for the constructor.
17:42You do all your setup stuff in there.
17:51Down at the bottom, we Dojo connect to the map's on-extent change event and call our model's update extent method.
18:05Now here's the interesting backboniness that's going on here.
18:11In our update extent method, we just sort of wrap up just sort of the fundamentals of the extent into this object right here...
18:18...just xmin, xmax, ymin, ymax, and we passed it to [unintelligible].
18:24Model.set in Backbone land is magic.
18:29When you call that, and the properties of the object you pass to it are going to be set as attributes of the model.
18:38But there's more.
18:40What also is going to happen is the model's change event is going to get raised.
18:45So remember, views reacting to changes or events on model.
18:49In this case, it's going to be that change event.
18:53There's some other cool stuff that kind of goes along with that.
18:55You could...there's some extension points, a validate method that you could implement where you can, of course...
19:01...put your own validation logic.
19:04If you return anything at all from that method, Backbone will raise an...well, an error event, not an exception, an error event...
19:16...and not set the attributes on that model.
19:20And then there's other stuff.
19:21If I'd instead called Save and given this model a URL, it would use Backbone's RESTful JSON goodies...
19:29...to post that to the server before setting it on the client-side model.
19:37And so this is our view.
19:38It's responsible for that logical bit of UI that displays the current map extent.
19:45So this time, of course, we extended from Backbone view, we're extending Backbone view.
19:49There's an initialized, you know, our constructor again.
19:52And here, here's some of the magic.
19:56We listen for the model's change event and call render.
20:00This is a pretty standard, I think, Backbone view.
20:05We grab a reference to the template, and we listen for the model's change event in the constructor.
20:11This right here, EL, that's Backbone magic, too.
20:15That just tells the view, Hey, you live in and are responsible for the DOM element with the idea of info.
20:24And then the render function, that's standard Backbone stuff, and that's a standard, pretty standard Backbone implementation of it.
20:32We get our content by checking our model to our template function that we cached up here in the constructor...
20:38...and then we pop that into the DOM inside our [unintelligible], DOM element.
20:44But take a closer look at this, what we're passing to our template function.
20:48We're not just passing the model.
20:49The model, the Backbone model has all kinds of properties and methods on it...
20:54...but none of them are xmin, xmax, ymin, ymax, right?
21:01Those are kind of hidden down there in an attributes cache, and to get at them, instead of calling, well...
21:07...kind of the flip side of set is get.
21:10You call, if you wanted xmin, you'd say, this.get or model.get xmin.
21:17And if you want to get at all of them, an object containing all of the attributes, you'd set on that model, you'd do this.
21:25You know, this.model.to JSON.
21:27So that's what we're going to pass to our template in engine.
21:34Okay. So that's all well and good. Super simple example, but if that's all you were going to do...
21:40...you surely wouldn't use Backbone to do it, because there's not much payoff in an app that simple.
21:54But the next demo is still really fairly simple.
22:06Still fairly simple, but it's a little bit more like the kinds of apps I build for real.
22:12It's, you know, we've got a map.
22:15We've got a Search button, and you click the Search button.
22:20You draw a box on the map, and it queries one of Esri's map services to get demographic information...
22:32...about population information on census block groups.
22:38And then we've got some behavior here.
22:39If you hover over one of the rows, in the table it highlights it on the map and bolds it in the row.
22:47Still pretty simple but, like I said, a little bit more like the real apps that I build.
22:54So how do we build that?
22:58Again, again I capsulated the map inside a Backbone model.
23:03We got the initialized function again.
23:06This here, I don't think Brian mentioned this.
23:09Backbone has a dependency on another library called underscore-js, which is pretty awesome.
23:14It's got...it's sort of a just a utility library that's got loads of useful little functions...
23:22...a lot of stuff to do with iterating over a raise and filtering a raise and finding elements in a raise, but other stuff, too.
23:28This particular one is used a lot in Backbone.
23:32It's for handling context, so it says, Inside these named functions, make sure this means this class.
23:48...but then in this one we use a draw toolbar to specify our search extent...
23:54...and then we listen to its on-draw end event and call our own update search extent method.
24:06So then it updates search, all we do, this is a little different than the last example.
24:11What we're doing here is we're triggering a custom event.
24:16In the previous one, you know, we just set properties on the model and let Backbone raise its change event.
24:23In this case, we're raising a custom event, search event updated, and that uses Backbone's events module.
24:35This is something different from the last example, too, and it's something I haven't done except on this demo.
24:42I'm not totally convinced it's a good idea, but I think it's worth discussing.
24:48I think it might be...I might be on to something there, but let's look at it.
25:04So, you know, there's our feature layer in selection mode.
25:10We listen. We Dojo connect to the features layers on selection complete event.
25:15We passed in that map model that we just saw into the constructor and we hang onto it...
25:20...and we listen to its search extent updating event that I just showed you we raised when the draw toolbar finishes drawing.
25:38Oh, right. And then so when that search extent is updated, all we do is we grab the geometry that we got passed...
25:45...and we set that on the query and use that to select features on the feature layer.
25:53And then I already showed you where listening to the feature laye'rs select features event...
25:59...and we're doing a little bit of underscore magic there to sort of massage that feature set that we get back...
26:05...and then we're passing that to the collection's reset method, and that's analogous to the model's set method...
26:12...and ultimately what's going to happen there is the collection's going to raise a reset event.
26:23This results view, this is responsible for that whole results table at the bottom and the title of the header above it...
26:30...and there's nothing else there, but if there were, say, a button to export that table or something like that...
26:35...it would be responsible for all the stuff associated with that.
26:39And I use this...I've been using this pattern a fair amount, and what I like to do is, I use Backbone's render method...
26:49...I call in a constructor and only then to just set up the UI initially when the page loads and then I listen to the collection's reset event...
27:00...and then I call an update method.
27:02That's my invention, not a Backbone thing, so that I only update the rows in the table when the data changes...
27:11...not the whole...not all the other bits of UI surrounding the table.
27:17Now there's a bunch going on here in that update method.
27:19But really what it comes down to is we're looping over the collection and for each item in it...
27:26...we're instantiating a result item view, which we'll see in a second, and then we're rendering it not to the DOM but to an array...
27:34...and I'm popping that array onto the DOM.
27:36We do it that way just because performance is going to be a little bit better.
27:40And that might seem like overkill, but I think there's an important benefit that you get by doing it that way...
27:47...and we'll talk about that in a minute.
27:49That's the render function. It's really kind of fairly standard, you know, Backbone boilerplate.
27:57We're just setting up the DOM there.
28:01So this is that result item view, and this is what gives us the, when you hover over the table row element...
28:11...it highlights it on the map and bolds it.
28:18Previously what I would have done is hang an HTML5 data attribute on each TR that holds the object ID.
28:27But that's no good, right?
28:29One of the reasons for using Backbone, one of its advantages, is to get away from storing little bits of state all over the DOM, right?
28:40That's what your model is for.
28:41The model holds the data.
28:43So by having a model or, sorry, a view for each TR that's backed by a model, we can get at any of the data we need to anytime.
28:51So first understand that we have to look at this.
28:55This is more Backbone standard stuff, the events hash.
28:58This is how you hook up your...any UI events for your view, and by doing it...
29:05...I mean, you could do it with Dojo connect or whatever, but by doing it that way, it will manage context for you, [unintelligible]...
29:14...and it will also allow you to not have to worry about, well, is it in the DOM yet? Do I have to use bind? Do I have to use live...
29:22...or, what's the new one, what'd they just switch to, anybody?
29:29What is that, Brian?
29:31Oh, Event Delegation, well, it all uses Event Delegation, but it's Delegate is the new one.
29:36Anyway, when you do it this way, it's using Event Delegation for you, I'm sure, but standard Backbone way of doing that.
29:44And the syntax is, you know, an object, and the properties are the events...
29:52...and the values of the properties are the functions you want called.
29:55And that's for events that happen at your top level UI element of your view.
30:04If you want to be more specific and target say a button that's inside your view, you just use a selector right in front of that mouse center...
30:12...you know, a specific selector space mouse center.
30:17Not wild about that syntax really, but it works great.
30:22So on mouse center, our mouse center function gets called, our mouse leave, our mouse leave function gets called...
30:27...but what's really important here is this, what I was talking about before about not hanging, you know, state on our UI...
30:36...is that right there.
30:38Our view is backed by a model, so to get at data from that model, we just call this stop model.get and specify the property we're after.
30:47And we've got our object ID, and then we can just use that to find our feature in the feature layer and change its symbol to highlight it.
30:58Another big advantage of Backbone...Backbone...I think that Backbone is not very opinionated really...
31:05...but it sort of nudges you in the direction of good modularity and structure to your code...
31:11...and that, of course, lends itself really well to testing.
31:15Like Brian said, we used QUnit because I was learning a lot of stuff on this, and I wanted to stick with one thing that I knew well...
31:24...so my head wouldn't explode, and then, of course, with QUnit, Sinon.JS, which is a library that gives you test spies...
31:34...and mocks and other goodies that are really helpful, even if you're not using Backbone, but particularly if you are.
31:43This is just, you know, you got to load, of course, your scripts that are under test along with the libraries they're using and then...
31:50...of course, your test libraries like QUnit and Sinon.
31:56Actually, let's...I'll show you what that test runner looks like.
32:09So we're going to go to the test runner and it'll just run the tests really quickly.
32:14So that's it. You get that with QUnit.
32:16It's really nice.
32:18It's...there's a lot of red there because one of the tests failed, but that's on purpose just so you could see what that looks like.
32:29And then, this is what your test might look like.
32:37This one is kind of a contrived one, but so that top line there, you can put...QUnit allows you to put your tests in modules...
32:45...or not and specify a setup and tear down function. Nothing happens in those in this particular case.
32:54But then the test...this is the test.
32:56So we arrange by setting up a spy, =this.spy, really simple.
33:01And the spy is really cool.
33:03It's just a function. I didn't know about this, actually, before this...you know, before getting into Backbone.
33:09It's just a function that keeps track of how many times it was called and with what arguments and probably other stuff, too, but...
33:15...those are the two things I was most interested in.
33:17But then we...we use that spy to...as a callback function for our...for events that happen on our map models.
33:27So we say, mapmodel.bind, that search extent updated event that we saw before, to the spy.
33:34And then we act.
33:35We set up a geometry and call map model, update search extent, and then we check our spy.
33:43You know, we say, Hey, spy, were you called once?
33:45If Yes, the test is going to pass. If No, it's going to fail.
33:49And then you can also do...well, there's a whole bunch of other stuff you could do.
33:54That one we just saw, there's actually another assertion.
33:57It's spy.calledwith and then you give it the arguments you expected it to be called with.
34:08Okay. Industrial-scale stuff.
34:11We are building, almost done, a data access portal for a Colorado department of transportation.
34:26We're going to look at that one, traffic data.
34:30We used Backbone for these.
34:32So this is...it's an app that allows you to basically select traffic stations, traffic count stations...
34:40...in various different ways using the map or these, you know, query form over here.
34:48You can select it by route number and reference points.
34:52You can select by city and county.
34:54I mean, if you know it, you can select a specific traffic station by its ID.
34:58And then once you've done that, you see the one or more traffic stations you've selected here...
35:05...in a couple of different views on these different tabs, and then if you click on one of those...
35:11...you get the actual count data associated with it down here at the bottom.
35:17So one thing that I've learned...I've only done a handful of Backbone apps at this point...
35:23...but one thing that I've learned is, it really pays off to spend some time up front really thinking about...
35:30...okay, What are my views? What are my models? How are they going to fit together?
35:33How are they going to talk to each other?
35:36Is this a view right here, just that, or is this whole thing a view?
35:41You know, that kind of planning is going to pay off.
35:49Okay. So it's alright. So what I ended up with here is, that's a view.
35:55The map is a view in this case.
35:58That's a view sitting right next to it, all that other search stuff.
36:01They share a reference to a criteria model.
36:05This stuff down here listens to change events on that criteria model.
36:09There's a view on each of these tabs here.
36:14They all listen for that, and then I'd use that same technique I showed you a minute ago where each row is another view...
36:22...so that when you click on it, it can raise an event that these views are listening for...
36:28...so that they know when they need to go get data based on the traffic station you clicked on.
36:34So let me really hurry and show you how that actually works.
36:46[Inaudible audience question]
36:49No. I'm just a Mac idiot. I could just tap in like I do on my Windows machine.
36:57Okay, so this is it.
37:01If we scroll down a little bit, you can see that there's no, you know, no data selected, but I'll select a route.
37:17This view down here at the bottom, you know, caught that event, knew to go get its data, and update itself.
37:24These others right here, the other views on these, they know they're dirty, but they haven't gone and gotten them yet.
37:29We wanted...we knew there was going to be a lot going on here, and we don't want to make extraneous XHR requests...
37:34...so this one will go get itself now...happened pretty fast.
37:39And then if we scroll down here to the bottom, you know, we haven't actually selected one yet...
37:46...so these views haven't updated themselves, but when we do...
37:52... they'll know to go get their data associated with that traffic station that we clicked.
37:57That was probably more than a minute, wasn't it? Thanks, Al.
38:01[Inaudible audience question].
Brian Noyle and Mike Juniper of DTSAgile introduce the Backbone.js framework in the context of existing Esri web technologies.
- Recorded: Mar 28th, 2012
- Runtime: 38:16
- Views: 1152
- Published: Apr 30th, 2012
- Night Mode (Off)Automatically dim the web site while the video is playing. A few seconds after you start watching the video and stop moving your mouse, your screen will dim. You can auto save this option if you login.
- HTML5 Video (Off) Play videos using HTML5 Video instead of flash. A modern web browser is required to view videos using HTML5.