 this thing on. All right so I'm glad everyone is up bright and early. This is the third year doing the conference and my third year talking about at it. So the first year I did sort of an intro and of Backbone.js and an overview with some live demos and stuff like that. Let's see. And the second year I talked about sort of my favorite design patterns and sort of the philosophy behind it and so you know talking three years and you're all about the same thing gets a little bit tricky but I remembered that I made a joke the first year that Backbone is a small enough library we could probably do a code review and go through the whole thing in the amount of time I have to talk and I figured shit that'd be a great idea for the final Backbone conference to try to bang through the whole thing or probably not going to be able to do the whole thing but at least as much of it as possible. So I have to apologize in advance if this is a little bit too much code in the morning like eating your vegetables first thing but we hear that apparently popcorn and soda becomes healthy at 12 o'clock so I guess we'll get back to the junk food shortly but I think it'd be useful at least getting started to get sort of a good foundation of Backbone's internals and how it works and more importantly why it does things the way that it does. So in the aim of usefulness over perhaps funniness I think we'll look at some code so right so I'm calling it climbing the mountain probably be better name would be a deep dive but I didn't have any good undersea pictures to show you so we're going to call it climbing the mountain instead. Getting off to the top and I hope this code is yeah that's big enough for everyone to see our resolutions a little bit less than than we thought but this should work out pretty well. So the first thing you notice in when you dive into Backbone is sort of the way that it has to set up itself in in context with the with the global and the rest of the windows so whether you're using AMD or using common JS or you're just using old fashioned globals we have to do the sort of rigourmal to get it to work in all three and you can see what's happening here is the bit that's being passed in the exports there is the object that Backbone is then going to get attached to so if we detect that we're inside of AMD we're going to set it up we're going to you know depend on underscore and jQuery and the exports object and stick it back out on exports and otherwise if we're in common JS if we have if we have a require function that we can use we're going to pull an underscore because that's the only thing that you tend to use when you're on the server you don't necessarily want to be loading up jQuery inside of your node web server but you might want to be using your backbone models and then otherwise if it's global then we we just use a naked object to stick Backbone onto there's no special exports that's available and we use underscore and then we fall back to different things that you might have configured your backbone to use with so maybe you're using jQuery and if you are then we use that otherwise Zepto or Ender will do or whatever you decide the dollar sign sort of DOM library should be so I'd like for this sort of thing to die a horrible death in the future I think this is really hideous way for like widely used libraries to have to start it's just kind of ridiculous and hopefully with you know modules in this next upcoming version of JavaScript that'll happen eventually but until then we have things like no conflict so if you are working in a in an old fashion if you're writing a library or even a module to work with regular JavaScript and you're not using a module loader a really nice thing you can do if you're namespacing everything down underneath your name is provide a no conflict function and all that that is is basically stashing I think I have a mouse that will appear or maybe it doesn't appear oops so all you're doing is you're stashing a a reference to what the previous value of Backbone was before you load your script you just take save that out and then you add a function that captures it in the closure and so if they call no conflict you can you can get back a reference to this version of Backbone and you can leave the previous thing that was called Backbone alone in the window and so that lets you have compatibility and ideally you'd never have this you wouldn't want to have two different versions of the same library running on the same page because it's a waste of bandwidth but the real world is not the perfect world and I can say that at the times where I work we have a great great many graphics on pages where there's maybe two or three different versions of jQuery and two or three different versions of underscore because of different libraries or at different times and because they know conflict with each other it's not an issue so now the sort of the basic core thing getting started with Backbone is the inheritance function that you might be familiar with so when you extend a model or a collection or anything like that basically we have this little helper function that does the basics of what of what sort of JavaScript prototypal constructor setup is all about but you need to do a little bit of a dance because if you're setting a prototype chain in JavaScript you have to have a concrete instance of the thing that you want to inherit from and you don't want to instantiate an actual copy of that instance because the constructor might have side effects it might be saving itself to the server it might be going out and touching the DOM so you need to do this sort of wiggle removal where you make an empty child constructor function stick the prototype of the thing you want to inherit from on to the child make a new one of those that's the surrogate that you see here and then inherit from that and then set your prototype to be that new sort of naked object that has the prototype of the thing that you wanted in the first place so this is one of the reasons why I guess classes have been discussed for future versions of JavaScript and are are still in the works in the design phase so that you don't have to do this kind of dance and then the one extra thing that backbone does here when you when you call backbone.model.extend and make your own class is to copy over the properties the static properties from the parent class on to the child so that you get to keep those also and you don't just lose those when you make a subclass so you get prototype chain pointing to the instance methods and you get the static properties copied over onto the actual reference and then you can go from there and then you can see down at the bottom how we're adding this extend method it's just a it's just a function that we can attach to all of these basic classes to give it to give them that capability so after the basics sort of the heart of backbone is the event system and that's really core to basically everything that it is right so backbone at its heart is a structured way to deal with your data and your UI and the and the and you can do that both directly procedurally by manipulating them and looking at them and writing code that works against them but then you can also reactively by listening to events and reacting making changes updating your UI having computed properties having models change based on the state of other models using events so there's the to get before we get into the nitty gritty of how events work there's a little bit of sugar here for handling recursive sort of calls so when you when you call a method on events when you add an event to listen for something or when you trigger an event you can pass just the one event you care about or you can pass a space delimited list of event names that's what the event splitter rejects up top is doing it splitting up the event names or you can pass a key value hash with the keys being the name of the events and then the the values being the callbacks that you want to register and so all that this little events api thing is doing is it saying when we call a method if we're actually doing more than one thing if we're actually listening to three events or five and not just one then we'll recursively call the function that you tried to call in the first place and then pass it the same arguments so that's all this is doing is saying if it's an object we're going to recursively apply it to every key and value pair in that object or if it's a list if the event splitter is a matches against the string we're going to loop through every single name in there and then recursively call the same function you tried to call and sort of implemented that way so this is a nice little bit of sugar we can use for all of those core event methods if you ever looked at this in the source could work confused as to what exactly it was doing that's what it's doing so now inside of events when you bind an event the first line you'll see there is if not events api then you just return because the events api thing is what's going to go through and make all of those extra calls so when it when it when it returns true and you're allowed to continue because it's a singular call and not a recursive call then basically when you bind a call back to a model it's going to lazily create the storage for where that call back gets stuck so so conceptually what is an event an event is a function that you're listening to a an event of a given name and then when that thing happens we need to go look through look up that name on that object and find the list of all the callbacks that have been ever been registered to respond when that thing happens and then call them in sequence that's sort of conceptually what it does and so the machinery of that is you have to build a storage for that and we don't want to have storage for everything that might possibly ever be called so instead you do it lazily so we say if there isn't an events hash at all if nothing's being listened to we don't even have one if we do have one we make an array for the name and then we push in this new event which is just an object tracking what the callback is what the context is and then the ctx might be a little bit confusing so the context is the original context so that you can look it up later because you can unbind things by context and then the ctx is what we actually use defaulting to this because we want to have a value but if we just use one or the other of those we wouldn't necessarily know what the correct value was when we had to do the bookkeeping later so we have to keep track of both of those things and now once is a little bit interesting because it implements itself as an underscore dot once wrapped function so a function that can only be called one time and you'll notice how it unregisters itself the first time it's called before continuing and then it just calls on to add it to that to that tracking now off is a little bit more fun I hope that's legible a bit of a fine mess here so it does the same recursive events API call to start so you can unbind multiple events or spaced delimited strings and it works by specificity so the idea here is that when you want to unbind events you can unbind all the events on an object period you can unbind all the events that have a particular callback registered for just that callback you can unbind all the events for a given context you can say everything that this object is listening for everything that this model is listening for I want to get rid of anything on this object or any combination of those so you can be as specific as you want to be with exactly what set of events you want to remove so this stuff is sort of handling that so we're saying I mean that first case is the quick case right if you're not going to unbind any particular event and you don't have a callback that you care about and there's no context then you're just blowing away all the events so we set this dot events to undefined and that's it that's all we have to do we just blow away the entire storage system otherwise you have to loop through so we have to say you know for which if you passed in an event then it's just that one otherwise it's all of the names in that hash we loop through all of the names and we delete we delete the entire list if there's not a context or a callback otherwise we sort of do the opposite where we go through each registered handler in turn and we say is it something that we want to keep is it something where either the callback is different or the context is different and if either of those things are the case then we want to keep it and so we just basically build up this new list of remaining events and then replace the existing events with what was left and if there's nothing left at the end then it's then we can delete the thing and avoid this entire bookkeeping in the future so your event system speeds up you don't it doesn't get slower and slower because you have more and more bookkeeping for things you're not listening to anymore it sort of cleans up the bookkeeping after things are removed so that's removing events now for triggering events it can be similarly recursive we use that same events API sugar towards the top there and and you'll see it sort of it doesn't do very much right we're just looking up which event it is and then calling trigger events on that and then we're also doing it for the special all event so in backbone you can have an all event you can say model dot on all and then have your callback which means no matter what the event is it's like binding to star no matter what the event is it'll run the callback which is very useful for sort of meta level stuff where you're where you're delegating your forwarding events onto something else or you want to do bookkeeping and you want to listen to find out what's going on underneath the surface so here you have the little check you say if we have anything listening on the all event then we want to trigger it we don't just trigger it blindly we only trigger it if someone is paying attention to it so what is this trigger events function you might ask well it's this ugly thing and now this is is gross but it's actually a little optimization and unfortunately it actually matters so the sad the sad fact is that in most javascript engines these days and even more so in older engines call can be faster than apply if you're trying to call a bunch of functions or dot apply a bunch of functions apply being the form where you can take any number of arguments in an array and call being the form where you pass positional arguments so we're optimizing we know that most callbacks to events or we're saying the most callbacks to events take you know up to three arguments and so if it's less than we're saying if it's less than three arguments in the list it actually speeds things up to manually do the call here then it does to do the apply which is the default case and so this is a little bit sad but it's a nice little it speeds things up when you have a whole bunch of events firing in a tight loop and I remember once doing a far more terrible and awesome version of this with case up to 32 going out to the right yeah and it was actually we had a formatted a sort of a pyramid getting longer and longer and longer with the little ascii art skier and javascript comments going down the side because there was some crazy I think it was it was a cross frame bug in IE 7 with certain types of frames where if you try to call a function from the other frame apply didn't work and call only worked up to 32 arguments so you know go figure and I don't remember what exactly it was we tracked it all down we needed to build this you know instead of apply call with up to 32 so this is at least a little bit better than that all right so now listen to also part of events is sort of the inversion of control version of on so it uses on internally as you can see right there but it keeps track also from the other side so so you can conceptually right you have model dot on change do this now the model is where the bookkeeping is happening there but the do this might be a function on the view to re-render or to do something else so you might want to keep track of it so that you can then unbind later keep track from the other side of the chain keep track from the view side so view dot listen to model change right and so basically all that we're doing is we're we're saying what is the object that we're listening to and let's make an ID for that object and keep track of keep a reference to that object so that we can then unbind it in a moment on the next slide I'll show you that and so once is the same sort of pattern where we do the underscore dot once wrapping to ensure the functions only ever called one time and we tell it to undo the listening that first time that it's called so the useful thing about doing listening to is that when you stop listening you can call it from the right side so why would you ever want to do stop listening if you have a view in the view is listening to five or six different models and then the view is destroyed so you want to get rid of the view in order to prevent memory leaks or or events happening that that you don't need anymore because the view is no longer relevant you'd have to go through to those five or six different models and unbind those listeners and I would stop listening you don't have to do that because you can just say view dot stop listening and all of those models that it had kept in that kept track of it will just go through and unbind all of those events and get rid of them so that's sort of the idea here for for var id and listening to it looks up those objects and then it calls off and you see how it calls off passing the the callback if one exists but the callback might not if you didn't specify it but the important thing there is this as that third argument so basically it's saying for everything that I'm bound to everything that I've set up in the first place unbind all of those events and so that's that's pretty handy next up after events is backbone models so models are sort of the the core of your data layer for backbone and getting started with them the important thing to note about sort of the constructor and how models are set up is the order in which things are done because this is not necessarily obvious although hopefully it is so first the attributes are parsed out with your parse function and defaulted to their default values and then they're set so your initial attributes when you first create the model and you pass in data those are set before initialize is called so when you have your initialized function and you're doing your your initial setup all of your data is already there your attributes already ready and it could be the other way around there's some use cases both ways but this is I think a little bit more useful generally so model basics these are things you can override to jason and javascript is a method with a pretty terrible name because it doesn't actually give you jason right the idea is it was sort of a crockford spec to to jason is a function that you should return what you would like to be serialized into jason so in this case we return a clone a shallow clone of the attributes of the model is considered to be its jason representation if you want to do something special that's fine you just override to jason return the jason serializable object that you'd like to have and then the same thing for sync it's just a hook that exists so that you can override sync at a model level so you can say my this type of model special it doesn't go to my usual API endpoint it goes somewhere else and I want to override it and and do my other thing and so fundamentally a model is sort of the enhanced change framework around a basic key value object and so get is just the simple function for looking up the attributes in your attributes hatch and there's a little bit of indirection there so that you have the symmetry between get and set so that we can do the events when attributes change and then a model is considered to have a value if if to have an attribute if the value of that attribute is not either null or undefined so this is something that some folks don't know about javascript we get that's probably the number one most frequent reopened constantly ticket to I guess a lot of things including backbone but coffee script especially where not equals to null is actually checking against both null and undefined if it was not equals equals it would just be null but not equals to null is null and undefined both um so that's good little tip um now set is really the the most fun uh hairy part of uh of model so when you're setting attributes we have to go through we have to um put them in we have to validate if we're going to validate and we have to figure out what the changes are and what has changed and now this is actually a little more um complicated than one might think because um you're dealing with so basically the idea with backbone um events is that they're synchronous so that you have nice ordered behavior where if you call set on a model and you have listeners listening for changes and reacting on the next line after you've called set you can depend on the fact that all of your changes have been applied everything that's listened has reacted by that point you don't have to wait for another event loop to run or anything like that um so there's actually a bit of tricky bookkeeping because you can have a model set call that that then uh something listening to that change call set again on the model inside of that set call and so on you know add infinitum hopefully not because then your browser hangs up but uh it can it can it can go more than one level deep so we have this changing flag to say are we in the middle already of a change cycle are we already more than one level deep because if we're more than one level deep we don't want to start from scratch with our previous attributes our previous attributes are still you know we we keep a reference to them and we just basically keep on building up the further the more deep you go in the more and more nested change events you have we keep building up what the diff is from the previous state until you stop and at the time that you stop all of that gets flushed back up so the basic idea here is you go through all the attributes being passed in to be set on the model and if the two aren't the same using underscore equality so that underscore dot is equal sort of a deep equality comparison if they're not the same then we say that that attribute has changed and we and we push it into that list of things that have changed and then we keep going so in part two this is the rest of the function once we've sort of built up that change list we need to trigger our events so first we do the specific events so we say that this attribute has changed and this so that's change colon attribute and that's where all of those changes are triggered and then um there's you can see this pending bit so then we say if we're not doing a silent set and um the while this dot pending is what I just talked about um with the nested loops so basically as long as as long as the this dot pending is still set as long as we're still deep within a nested change we don't want to have so basically the idea is you can have many nested changes together we only want one change event at the end of all of those things to be fired we don't want to keep every time you step back out we don't want to fire multiple change events for the same thing just because you happen to have it go together so while this dot pending is true we haven't made it all the way back out of that list yet um and so we we avoid firing it and then at the very top level we trigger that change and say all right that cycle has completed you have a change here's your old diff here's your new set and you can keep going so that's the fun little nasty bit of doing so if you didn't do synchronous changes this wouldn't be um so much of an issue because you wouldn't be able to know about it until it had already happened but here you can you can mess with it in the middle of it happening um so the sort of the the um sister functions to set are unset which is simply a call to set again so one thing that backbone tends to do is to implement its primitives sort of in terms of other things internally um so in the case of in the case of unset it's really just a set but you happen to set all of the values that you pass to undefined and and and or delete them so it's just an unset true option being passed into set that'll do it and then the same thing for clear so for clear what we're saying basically is is we know what our attributes are this dot attributes you know four key in this dot attributes is the list of all the attributes we've ever set so we just clear all of those out and then um has changed is pretty simple it's just figuring out if there's any changed properties at all on the object and then looking up um if that particular so changed is that again that hash of keys and values that have changed since the last set and we can just check if it even has that attribute present in the keys and if it does then that's something that's changed and we'll see you'll see later on how we can use that to implement some other cool things um so going going further with this idea of models having changed attributes and your app being able to tell what's changed um changed attributes is a function that either returns a list of the uh sorry a hash of the key value pairs of all the attributes that have changed in your last set or you can diff it sort of speculatively you can say given this set of attributes how has that changed my model and that's what that diff does um and then so that's different than previous attributes right so previous is the previous state of your model changed is how is it currently changing um and so you can say all right I've got my model and I know what the attribute is what's the last what's the previous value of that attribute whether or not it's changed um and give me a copy of the previous state of my model which is useful for implementing undo if uh if that's something that your model needs to be able to do going forward um the interesting part of uh models sort of so you've got this client side state where you're setting values and you're and you're reading them and you're using them and you also want to persist that to the server so how does that work um basically when you save a model you can save it with a fresh set of attributes you can say dot save and pass in a list of stuff to save and that stuff um needs to get set so you can see how if if there's attributes passed in and we're not waiting for the server then we set them right now on the client side um and and otherwise we validate them so validation is sort of the default thing to do if you've defined it for your model on uh on attributes now so save has this interesting sort of duality where in normal case backbone is optimistic um and when you save a new set of attributes it will set that attribute set on the client side and your UI will update and then it will make the request to the server and hopefully that works you'll get back the success callback but if you say wait true if you ask it to wait for the server to respond then it's a pessimistic update and uh it will not change your model yet it will simply make the request to the server and when the server comes back you can see on the right hand side there it merges it parses the server attributes and it if if you're waiting it'll merge those server attributes into the attributes you wanted to save before setting them back on your model on the client side and so you have sort of optimistic and pessimistic um options depending on what you want to do and optimistic is the default one and that's how it's sort of implemented here so one slightly tricky point of interest is that you'll notice down here um if there's attributes and you're waiting we actually change the model attributes temporarily and then on the other side over here if there's attributes and you're waiting we set it back to the original one because we have to so basically for two json to work right your two json function can be a custom function that uses the the attributes of your model to um figure out what to send to the server so we have to temporarily during during just the course of this function patch in the optimistic attributes so that you can make your json representation and send it to the server to be saved and then we stick back the previous ones at the end of that call so that you're waiting for the server to acknowledge it before they actually get set in that success call back and that's a little bit of uh rigor moral that we do to make that work so model destroying um not super fancy except the interesting thing here is that we call stop listening by default on the model so by default if you've been using listen to on your model to make it listen to whatever it needs to react to by default all of its event handlers will be cleaned up when you destroy that model so that's a nice little quality of life feature um a little bit of extras on the model the way that the url is determined so so backbone models have sort of their restful um representation so every model ideally has a url where it's being put to or deleted from or being read from if you're fetching new data from it and the way that's determined by default is if you've defined a url root on your model or it gets it from the collection so if you have different collections of the same type of model that live at different endpoints like for example authors slash one slash books is a different endpoint than authors slash two slash books um and if the model is new if the model has never been saved to the server for its it's a url is just that base url where it'll be posted to it's a sort of a rail style convention where you post to the base url um to create a new resource underneath that url it'll give you back the id and then if there is an id um we have that base url plus a slash with a little bit of jiggery pokery to make sure we don't get a double slash in there and then um the url encoded id of the model is again that's just a default so you can override this function and give a model whatever url scheme you desire so validation so um the first is the this idea of is new where a model we consider a model has not been saved to the server yet if it doesn't have an id and that's just our convention so basically you know clients if you're building a robust application clients can never actually generate id's you can't trust the client to generate an id because it needs to be you know something that uniquely identifies your model um so if the model has an id then that means that the server has knowledge of it and there's a url for it on the server and it's been saved to the database so that's kind of just our convention for whether or not the server has been the model has ever been saved um it needs to be posted or put or the appropriate or patched or the appropriate option so validation here is just a little um convention they're actually so so you'll see there's this dot validate call to actually do the validation there is no validate function in backbone we don't define any validation for you but should you desire to validate your attributes you can make a validate function that takes in the attributes that you pass in and just returns it you know a either false or a or an error to to indicate that the validation failed and that there's an error you want to display um on the client side so we never make a validate function but that's something you can add yourself if you want to and then there's a bunch of little goodies from underscore that we can proxy into the model prototype and get there so this is kind of a fun technique this is useful for many other projects you know your own your own libraries and your own um applications where you you have underscore functions that are useful on the data that you're working with and you want to give them a more convenient way than having to call them sort of externally through underscore so here what we're doing is we're taking all of those methods those things in the list and we're sticking them on to the model dot prototype right we're saying model dot prototype dot that particular method is a new function that then applies it against the um the model there and so that's sort of a nice little way to get to get those to be able to say um you know book dot keys book dot values pairs invert and to work with the attributes of your model all right so that's the end of models and now we can talk a little bit about collections and maybe pick up the pace a little bit uh collections are sort of they're really they're really where your data manipulation um goes to work with so models are nice having a discrete unit to represent a resource on the server is nice and having ways to work with it in a rich way are nice um but collections are how you really get sort of the power of working with a set of data and part of that is that they listen to events on the model and proxy them through so you have one place you can say i'm going to listen to this collection and whenever anything in it changes whenever any of the models changes the title or something's added or something's removed whenever anything happens inside of it i can just listen in one place and know about all of those changes that having to keep track of a whole bunch of listeners um so the constructor is not too fancy the interesting thing here is these is these options here the set options and the add options we're going to do that same trick where we use one function to implement sort of two different things and in the case of set will be adding and removing and merging if you're setting a new set of models on the collection you both add models you remove models and you merge models with just those options and then if you're just adding by default you're adding but you're not removing um so the same kind of setup that you see for models here you have a to jason function by default it's just a mapped array of all of the models to jason individually you can override it if you have a fancier thing you need some special wrapper around it or whatever and by default we have a sync that just uses backbone sync but you can have a custom sync and you can see how ad here ad isn't its own method it's just a set with the correct option so we're saying set we're going to default merging to false when you're just adding new stuff but if you want to you can override that by passing and merge true as an option so if that is delegating to set how does set work so here's the first this is this is the the biggest the biggest method in uh in all of backbone is set so the first part of set here is just sort of getting set up so basically what what is what is set in a collection when you set a new set of models in a collection you add models to the collection you remove them um you and you merge models in you can do this at a particular point in the ordered list the collection is or you can do it at the end you can have the collection sort itself when this happens or you cannot and um and then you have to trigger all of the events that correspond to all of these ads and removes and changes so first we're sort of parsing in the new models and we're figuring out if there's a position we want to insert them at we're figuring out if there's a comparator we want to keep this thing sorted and then we set up this these lists of models to be added models to be removed and a model maps that we can check for duplicates and see if we've already um seen this model before in this loop now we go through all of the models in the list and we see if that model if existing is equals to this dot get we see if that model is already present in the collection um and if it is and we're merging then we want to merge in those new attributes so we call set right there existing dot set attributes options and now here's this cool thing remember I said how has changed would come in handy before so we just set that the new set of attributes on that existing model now we say if it's sortable and we're not using a custom sort function we have a uh a comparator property and the existing model has changed its sort attribute then we set a sort equals true boolean flag so we can check right there we can say has the attribute that we care about that the model depends on for its ordering has that attribute changed after this call if it has we know we have to then sort the entire list later on to figure out what the new positions are so that's just a really neat way of using the bookkeeping to say if this particular thing we care about has changed we're going to do this more expensive operation later because we know we have to reevaluate the sort if we didn't know that we'd have to just resort every time um and so now if we're adding then basically we push the model into a list of stuff to be added and then um sort of the same thing down here for the ordering we push the model into the into the list of correctly ordered stuff to be added if we have things in an ordered fashion and now the last part of set the third and final part which I hope is at least somewhat legible so after we've we've called we've merged in the new attributes we now remove it we go through that list of stuff to be removed and we build basically we're saying if things aren't present in the list then there are things that need to be deleted and we remove those things um calling this dot remove and then uh and then we add the stuff after that so if there's a particular position for stuff to be added at we splice it in at that position splice those models in um one at a time and then if there is not a particular position we just push them on to the end also one at a time so you get your sequence of ad events in the correct order um and then after all of this if we need to sort if sorting is uh now it's now been determined that we have to resort this this set then we call we do our silent sort and then we start triggering our events then we say if this is if this is not a silent um set on the collection we're going to trigger all of our ads we're going to trigger and then we're going to trigger our sort event and we're going to come back out of there so the overall um sequence of things you'll get here right so you've just called set you've passed in a new list of stuff and you're getting all of these whoa you're getting all of these changes um so first you're going to get your changes you're going to get all the models that have changed then you're going to get all the models that have been removed all of those events are going to fire then you're going to get all of the additions and then finally you're going to get your sort and i'm going to skip over remove and we'll go to mutators so um we need to now implement array mutators for um collections in sort of in terms of those primitives that we've just established so pushing because we need to we need to use those primitives that we get that same behavior of being able to merge if we have to merge or um or more importantly triggering the events the appropriate events so pushing into a collection is just an addition at the end of the collection right popping is a removal from the end of the we figure out what the index of the last thing is and we just remove that one and then unshifting is the reverse so unshifting is an addition at zero and uh shifting is take finding the first thing in the collection and removing it and then slicing um is just pulling out a slice of of models from the middle so there's locators for sort of looking up things inside of your collection by indexes um one is by so again collections are sort of this doubly indexed set of stuff you have one indexes by the id of the models and one is the ordering that you've put it into so get is what gives it to you by id and at is what gives it to you by index and basically one is just looking up in that in our in our trackers of either your objects id or its client id its c id or its index just in the list and that's pretty simple and then where and find where you might be familiar with from underscore it's give me back models that match where this set of attributes matches the given model and now sorting there's a funny little hack in here so when you sort your you have a comparator on your collection that comparator can be a property that you want to keep things sorted by or it can be a sort function like custom sort function to determine how to sort your collection and we used to only support um uh sort of underscore sort by style comparators where the sort function takes a single argument which is the model and it returns back a value that is sort of the position in the list where it should be sorted to and so we just it turns out that's not you know if you that's a fine way to sort things for simple cases but complicated cases you can't just return a value because it depends sort of on what is next to you and you have to support the full style sort where you have you pass in two arguments one model and the other model you have to turn one if it's great if if first should be in front of the second negative one or zero depending on if it should go first the other one should go first or if they're if it should go first the other one should go first or if they're both considered to be the same and so now we have to support both the types of functions but there's not a good flag for that so we're um most of you probably know that in javascript functions have a length property and the length of a function is the number of arguments that it was defined to take it's not super reliable because there's some things you can do to functions like binding them that will change the length of the function but in this case if you're defining a function in line we can say if it takes one argument then it's an underscore dot sort by style function that expects one model and if it doesn't take one argument then it's just a regular sort that um takes two so that's how that works and finally sort of the heart of the collection reference tracking is paying attention to what events are going on on all the models in the collection so when we add a model to the collection we add a reference we listen to all of the events that the model is going to do all of the changes and all of the change properties and the and the and the destroys and whatever else you might be triggering on your models and then the same thing on remove reference so when we're done listening to a model we take off that all and then what do we do when the all is called well here's our on model event callback so basically when it's being added or removed and um and it's a different collection we don't have to worry about it um but if it's being destroyed if the model is being destroyed we might that we then automatically remove it from the collection so you don't have to remove stuff from the collection yourself when you call destroy on a model the collection is listening for that and it takes the model out itself and then if there's a change we care about changes in id so when the id changes we have to update our id mapping and so we're listening we say oh has the id changed if it has um then we need to change that reference there and then we proxy it through so basically whenever any model changes we trigger that same event on on this on the collection itself and so you can listen from the outside for model changes then the last thing in collections is this huge list of underscore functions which is sort of proxied through so useful things mapping over collections filtering collections to find certain models reducing finding out the minimum by specific criteria value in the collection or the maximum and um also you know the these things need to be proxied in different ways depending on how they work so the basic thing is the same as the model where you stick the method onto collection dot prototype and you just apply it against the the list of models there so basically args dot unshift list of models is putting that array of models as the context to the underscore function um but there's also a few methods that work not on models directly but on attributes of the models and so we have to to add an iterator that goes through to get the attributes for group by count by sort by so we say model dot group by sorry collection dot group by a property it's going to go through all of the models and then find that property and do that group so i think this is actually a pretty cool demonstration of how functional and object oriented methods don't have to be at odds with one another and how you know it's pretty you can find a real harmony between the two where we have this low level underlying library that's implementing these things in terms of function you know naked function calls against raw arrays and then with a pretty simple proxy you can take that list of stuff and attach it in object oriented fashion to be applied against these internal arrays of values and really sort of it's not really one or the other you can use the functional techniques as methods on your objects in a nice way um and i think this is a pretty cool little demo of that so i'm running a little bit short on time but i'm getting quite close views are very simple in backbone they don't do much and the best demonstration of that is how in the beginning of the views your render function does nothing right the default render function just returns this and so the idea is that you're going to use your favorite templating library whether it's underscore templates or whatever kind of templates or you're going to use react or you're going to use whatever the case may be to optimize your your views and do them the way you want them to do and a view a view in backbone is just a top level DOM object listening to events inside of it and and a top level DOM object for that view that always exists and it's important that we have ensure element here it's important that it always exists because that lets you have something to hang on to it avoids the old jQuery nightmare of i i have this thing where i'm binding this click handler and it doesn't work and why doesn't it work i can see the elements there right i'm binding it oh it didn't exist at the time that you bound the click handler and jQuery just failed silently you know we've all had that happen all the time so the idea is that if you're for a view if your element always exists it never does not exist if the view exists and you're delegating events always or at least as much as possible from that top level then your all of your events always work all of the time and you never have to worry about that and they're implemented efficiently because they're being delegated they're not being applied to thousands of individual DOM elements um we've got backbone dot sync which is not super fancy although it is pretty but it's not super fancy except for um that fun little method map up in the corner where we're mapping between crud and rest and and our internal terminology here um but sort of the basic idea is that when you create new things that don't exist yet you're going to be posting them to the server when you're updating them you already have a url and you're putting a new representation at that url and then patching is the new hdp method that's not widely supported yet but for doing a partial put um and and we have sort of that mapping right there and then we also have fallbacks for things like emulating hdp and emulating jason which are a little bit pejorative ways to phrase it in terms of arguments but the idea is that if your server doesn't support fancy methods like put and delete and patch we can do the override in the header and if your server doesn't support jason parsing we can send it as if it was a form instead of serializing it to jason we serialize it to a form and send it up and then finally the last thing i wanted to touch on is the backbone router just very quickly the router is sort of a list of um of of regexes that is applied against the url and it picks out which one matches and then sends those parts to you so there's here's the different kind of parts you can define in your routes if you're not doing a custom regex you can have a named one or an optional one or something that soaks up the rest of it and our regex bashing happens right here where basically we do this kind of cool thing where that root to regex right there that takes your url string that you've had you've added those little um sort of parenthesized or or named colon named parts you want to match and we turn it into a regex by replacing it with regex syntax and then calling new regex at the end and you'll notice that the regex is anchored to the beginning and the end of your url so you're always going to get a complete match when you have a root and uh and then we this extract parameters is the inverse thing we're basically with them we're mapping the uh the parts of your root back into the arguments because the regexes that we generated right there have have parenthesized capture groups so the first thing it captures the first argument the second thing it captures the second argument and those match up those align exactly with the roots that you've defined um and then I think this is the last thing that I wanted to talk about with um with backbone history so most of history is not that super interesting anymore because a lot of it has to do with hash change and um support for older IE's and all of that stuff will hopefully be irrelevant and dead soon now that push state is widely supported and browsers are being um upgraded but the one really fun gross hack for old IE so this is IE is so old that not even hash change is supported so there's no there's no push state there's no real urls there's no hash change you can't tell when the hash has been updated um but you have an iframe a secret hidden iframe that backbone is creating for you and writing new little fragment urls into so that it gets stuck in your browser history so the back button works properly in IE 6 and IE 7 and that is a horrible hack that I'm looking very much forward to deleting soon so uh thank you guys for coming out um I think that was about 40 minutes that uh I was supposed to use up and in terms of what's coming up for backbone there's gonna be a 1.2.0 out soon there's not tons of huge changes in it lots of little bug fixes and quality of life things the main change is that there's more hooks exposed internally so that people can write plugins that replace jQuery with their own non jQuery style native adapter to get increased speed so if jQuery wrapping is too slow for you because it's not the fastest thing in the world um there's you can replace it with sort of much closer if you're using modern browsers much closer to native style method calls and then get a little bit of a speed up with your with your view handling and uh so I appreciate everyone coming out so early in the morning and the fun thing about this conference is always not so much backbone in itself because as you just saw we pretty much did the whole whole shebang right there and uh and what you guys have done with backbone and what you do you know day to day with the libraries you're building goes way way way beyond you know what backbone itself is so it's not so much about what the library is you know we're not coming down from the mountain with new tricks or techniques or performance things you should definitely be doing it's more about what you've already learned how to do and sharing that with each other and the amazing shit that you guys have uh have built I'm always just blown away by the types of things that have been done with it and I think that's probably a pretty good segue into the guy we have coming up next so thanks a lot