 Well, thank you, everyone. It's really exciting to be doing this. Two years ago, three years ago, 2007, we did our first jQuery conference here in Boston. And then we had 70 people show up. And so I think it's pretty amusing now to have the meetup has now eclipsed the actual conferences we're running. So I wanted to talk a little bit today about a couple of things. It's pretty nice being able to talk to a group of people who already use jQuery, since I can talk about some of the more interesting things instead of just going over what are selectors and things like that. So some of the things I wanted to talk about today are a mixture of things that are either new in jQuery that were added in a recent release or things that we have had in the library for a while, but maybe we haven't done a very good job of talking about. So that's some of the things I wanted to talk about today. And then at the end, I wanted to wrap up doing some coding to show you what's going on. So to start, I'm sure everyone here is at least familiar with how you would create elements in jQuery. jQuery, in addition to being able to accept selectors into the jQuery object, also allows you to accept fragments of HTML. And this is something that we have for a while now. It's just a mapping for doing a document create element. You can do more advanced things. Once you have that element, you can start to manipulate it. You can change its attributes, inject content into it, attach event handlers, all sorts of things of that nature. The way you've been able to do this traditionally in jQuery is just use chaining. You do a method. The method returns to jQuery set again. You do another method, and you just keep on doing that again and again. In jQuery 1.4, we added an alternative to that, which is if you have the original little HTML fragment there, you can pass on an object as a second argument. And that object is all the things that you want to set on that element. So you can mix attributes. So for example, you can have ID or a class name or stuff like that. And those attributes will get set. But you can also do things like bind event handlers, like click, or even call methods, like add class name. So we include all the getters and setters, well, all the getters, no, all the setters, sorry. All the setters in jQuery so that you can go through and attach those. So you can have Xs like data, and I think what other ones there are there. But yeah, they're all there. And so this makes it at least easier. And you can probably do some form of maybe basic templating with it, take an object and manipulate it and inject it into future ones, things of that nature. So that's something that we like. Another thing that people aren't typically familiar with is in jQuery, the concept of end, the end of method. So jQuery does have this chaining where you can, again, it's one method after another after another. But the thing is, is that once you start chaining all these methods, it can get kind of challenging because the code becomes quite complex. One thing that jQuery has that is rather unique is the end method, because what happens in jQuery is that any time you do a traversal method, like find or parent or parents or previous or next, any of those that you're traversing around the DOM, that changes the jQuery object. It returns a new jQuery object with a new set of elements in it. But the important thing is that that new set of elements that's returned points back to the parent from which it came. So in this way, what you can do is, so for example here, we create our initial list item with an anchor inside. We find the anchor that's inside of it. Since we're just traversing inside this fragment that we're currently in, we manipulate it, we set the graph, we set the inner contents of it, but then here's the critical part, we call .end. Now what .end does is it pushes back off the stack. Since the jQuery object has a reference, the object from which it came, .end returns that object. So in that way, you can traverse back up to the original, the LI, and then inject it into the page. So technically speaking, this is a one-liner in that it's a whole bunch of method calls and it's all in a single statement. I tend to break down my chaining like this into a more readable format. But in this way, I think .end is particularly useful and it tends to make your code much more expressive, I find. One nice thing about using .end in particular is that it allows you to avoid having to save jQuery objects and variables. So for example, another way to write this code, we could have written, let me just copy this here. Let me see, I'll just write it down here. We could have written something like this. We said if our LI, that, and then we could have said li.find and then li.append too. That would have been, that's roughly equivalent. It's not nearly as good-looking. I don't like having to have all these extra variables lying around when they're just not needed. So at least in that way, I find it to be much more, again, much more expressive and at least doesn't clutter your code so much. Another thing that we landed recently, and this is something that you particularly have to worry about and that it's just something that jQuery does, but it makes your code much faster. So in jQuery, again, when you pass in your HTML, either to the jQuery object, or if you're doing it in a pend or a prepend or what have you, in all those cases, we now use document fragments in order to improve performance. And this is interesting because we can use document fragments to do caching as well. To sort of back up and explain what a document fragment is. So a document fragment is a relatively rarely used part of the DOM specification. And what a document fragment acts as is sort of like a very lightweight container for DOM nodes. So you can take this document fragment container and you can push some nodes into it. And what's really nice about it though is that when it holds these nodes and when you insert the fragment, the fragment just sort of disappears. And what's inserted in place are the nodes that were inside the fragment. It's this, think of it as like it's water soluble. All right, once it hits the, once it actually gets ejected into the DOM tree, it just sort of disappears and in its place are a whole bunch of DOM nodes. Now in this way, we were able to improve performance in jQuery. We did this initially back in jQuery 1.3 when we started using document fragments. And we got some big performance improvements by using this instead, especially in cloning all these nodes. The additional benefit though that we came to in jQuery 1.4 is that we can cache these. Now the nice thing is that since all these, since what we now have is a relationship between an HTML string, yes, so now we have a relationship between an HTML string and some document fragment. And what we can do is, what we do now internally in jQuery is say, have we seen this string before? And if we have, just use the previously generated document fragment. And then when we're smart about it, we don't try to cache like a couple of megabytes of HTML or something. We keep it to just small strings where that are highly repeated, injected again and again. So in those cases, it will speed up your code tremendously and you don't even have to worry about it. So I find it to be pretty interesting. And in that way, this brings up another point because I find that a lot of times you hear people talk about performance and specifically like one way is faster than another way of doing things. So for example, in jQuery, in I think in 1.3, you can inject this fragment in two ways. You can do something like this or you could do something like this. So you can do either of those things. They're functionally equivalent. In jQuery 1.3, the first way was faster than the second way. And someone wrote an article saying that you should only use a pen because it's faster. That may be really angry. So I rewrote it and now the second way is faster. So, but then the probably about equivalent, but the second way is definitely very, very fast. So because the advantages, because let's say let's take the example of you're injecting a whole bunch of dynamic content into your page. And you have a whole bunch of strings. Like if you're gonna go through and you wanted to insert in 500 different strings. Well, the absolute fastest way to do it would be to generate one really long string and insert that whole string in. But if you wanted to do it dynamically, if you're pulling some variable, it's something that you couldn't generate, I don't know, and put in a long string. The trick is that it actually becomes, when you do this, we can't cache it anymore because every single string that's gonna be inserted is unique. So we don't, we look at this and we're like, well we can't cache that because that's every single one is new. But the difference here is that if we were to do, let's say for example, find HTML or probably .txt, who, something like this, what this is happening is that this creation, this fragment creation is being cached. So the 500 times you do it, that HTML is already pre-built, already saved, doesn't have to be generated every single time. The only thing that has to be done is, find the a, insert the text, insert. So in that way, you get a big speed up. So this is sort of my moment to say, don't listen to people talking about performance because what they recommend frequently doesn't correlate directly with your application. Nothing beats sitting down, opening up FireBlog or your tool of choice and actually analyzing the performance characteristics of your application. Because I say this now, I say that this may be faster but maybe it's not in your application. It's really important to not just blindly swap all your code out for one thing or another without testing it first. So that's my moment. A thing that jQuery has that's really quite interesting has this whole data storage API. And this is something that a lot of really interesting jQuery developers have started to use and to build just interesting ways of building web applications in general. And so what this data storage API is, it's a way of attaching information to DOM elements that is different from attributes. So most attributes, like you have the ATTR method and you attach some method or string to an element. But the problem is that that information is permanently conjoined to that element. And the issue is that Internet Explorer has serious issues of that. So Internet Explorer leaks memory all over the place, especially for attaching functions, especially for attaching functions that have closures to external elements. So in this way, what the jQuery data store is, it's a way of indirectly attaching information to an element. What we actually do is we store this information in our internal data store and then we just correlate what, we give each element a unique ID and we say this element points this location in the data store and never the two shall meet. They're very separate and it cuts down on leaks in that way. It also helps to improve on garbage collection. Well, an interesting side effect of this, so the jQuery uses the data API internally. We use it all over the place. And the reason why we introduced the data API was to manage all these event handlers that were binding. So whenever you do .bind, .live, et cetera, we have to stick these handlers somewhere. We have to make sure they aren't leaking. So what we do is we stick them in this data property into events. So what's kind of interesting is that if you pop open any web page that's using jQuery and you find an element that has events attached to it and you say .data events, you can see the full collection of all the events that are bound to it. So it's sort of an interesting way of being able to see what's going on internally in your code. You can get some more, dig in and get some more information that way. jQuery has a whole bunch of different data things. Events is by far the most interesting one. The other ones are really boring, like toggling classes and stuff like that. Of course, you can remove the data as well, but the really nice thing is that jQuery takes care of all the garbage collection for you. So if a user comes along and removes an element, then we will go through and make sure all the data is cleaned up as well. So you don't have to worry about that data is living forever. We take care of it, we clean it up, and then it's something you don't have to worry about anymore. An interesting thing, this is something that may or may not exist in the next version of jQuery. If people start to use it, then it will still exist. If not, it's gonna go away. But we actually published two events. We have getData and setData. And these events are broadcast whenever you manipulate the data of an element. So here, if you were to say, you know, dotData test5, then it would actually, it would call getData dot test. And in this way, what you can do is you can write plugins that actually override the default behavior for getting and setting data information. So for example, jQuery UI is using this technique. And so that you can say dotData, some property in jQuery UI, they capture that, and then actually you can go set the real property somewhere off in their catacombs of information. But what's interesting about this is since you can override those values, you can implement multiple different layers and multiple different plugins that all are trying to access and get at the same data values. And this sort of brings up the next topic, which is event namespaces. Or I should say, well there's data namespaces, but building on top of that is event namespaces. So what event namespaces are is if you're attaching a handler to an object, to a DOM element, it's a way of giving a name to the handler that you're attaching. So for example, here you're attaching two different functions and you give it the name of plugin. Probably you pick a better name for whatever you're inserting in. But the interesting part here happens when you remove. What you can say is since you've given both of those methods a name, you can now say remove everything that has the name of plugin. So in this way, since you've given everything that specific name, it means that you no longer have to keep track of all those handlers that you're trying to bind and manage. jQuery takes care of all that for you. Because what we found happening is that when plugin authors were sitting down and writing complicated widgets and things, what was happening is that they would have to keep track of all the handlers that they were trying to bind and then they would have to figure out when the elements were removed so that they could garbage collect it. And it was just like this whole nightmare. I'm trying to figure out when things existed and when they didn't exist. But what we just did is, so we just gave the ability to provide a name to something. And once we added that in, it all those problems disappeared. So you may not hit this immediately in your application, but if you're doing anything where multiple, let's say there's multiple interactions, like there's multiple plugins interacting with a single element, or if there's multiple libraries interacting with a single element, attaching namespaces to it is a great way to make sure everything stays very hyper-managed. So because the problem is that if you were to say, you'll unbind click or unbind focus, you might be blowing away someone else's plugin code or you might be blowing someone another developer's code. And in this way you can make sure that you're only removing your code, this is the specific functions that you want to remove. We also have the ability to bind and trigger custom events. This is, so obviously in jQuery, we have all the standard events, click and focus, mouse move, et cetera. But you're not limited to just that. You can say, you can bind to any name you want. And additionally, you can trigger any name you want. And jQuery just gracefully handles the triggering of all the handlers that are attached. It also handles all the event bubbling as well. This is something that I'm going to be talking a little bit more about when I do some of the coding. But so obviously if you have your own custom event, that's not going to trigger a default browser action. Because if you were to, let's say, trigger a focus on an input, then the cursor will be focused on the input. But if you trigger a my plugin on an input, nothing's going to happen. That's for you to, yes, for you to implement. And so again, you can also, if you have custom events, of course, event namespacing works for those as well. You can give namespacing to your custom events and make sure they work gracefully. More complex though than just custom events is in jQuery the concept of special events. It's probably a very poor name for what it is. It's our events API. And it's a way of implementing at a very core of fundamental level how events should work. Now this is a way of providing a deeper mechanism of implementing an event. So like in jQuery itself, we have a whole bunch of special events. We provide it for, in this case, focus in and focus out. We provide it for change and submit in Internet Explorer. We provide it for mouse enter, mouse leave. So there's a whole bunch of events that we implement internally in jQuery to make sure that they operate how you expect them to. So like for example here, so there's two events that we added in jQuery 1.4, focus in and focus out. And what focus in and focus out do is that they will run whenever any element inside of them. So if you attach it to a table, let's say, it'll focus in will run whenever any element inside the table is focused. So this is something that's provided actually, this is actually something that's provided by Internet Explorer. There isn't a ton of things that Internet Explorer gets right, but some things that Internet Explorer gets right are the mouse enter and mouse leave events. Those are very, very useful. Those are two that we implement and focus in and focus out. So there's some events that we implement in all the other browsers. To implement them in the other browsers, what we actually do is we actually have to attach during the capturing phase of the event cycle. But this is the full code to implement those events in jQuery Core. It's not a lot of code to it. So that's something else that is very interesting. If you see Ben Allman there, he's writing in a very cool article on special events. I'm sitting here, I'm shaming him because he hasn't finished it yet. And so if you wanna learn more about them, you should pastor him. And because it's gonna be, well, I just say it is already very cool. If you wanna learn more, pastor him. Okay, so then like I mentioned before, submit and change events are two events that we implemented in jQuery 1.4. And we got those working universally across all browsers. Namely, working around the Internet Explorer, huge issues in the Internet Explorer, not only with how the events worked, but also the fact that they didn't bubble properly up the tree. And this ended, so submit actually wasn't that hard. What we ended up having to do is we had to watch for key presses. So watching from the users hit enter to submit the form. And when they click submit buttons, that was pretty easy. Comparatively to the change event, which was ridiculously hard and we're still battling with to this day. It's as, we have to essentially implement the full change state ourselves. It's incredibly complicated and very frustrating. If you wanna have a good laugh, read that code, because Internet Explorer is hilarious. So building on top of that, we have an event delegation. So we've had the live method in jQuery now since jQuery 1.3. And that's a way of just very easily replacing your existing bind methods with a way of capturing not only all the elements that exist currently on the page but all the elements that will exist. And this is sort of the beauty of event delegation. This event delegation works by if someone clicks on a table cell or input or what have you, the event will go from that element and then bubble back up the tree again. It'll go to the parent of that element and up to that parent, up, up, up, up. And what we do is that with live and with the new delegate method, we watch for that click to occur. And what's really nice is that we only have to attach one click handler. So for example, we can attach one click handler for a table and watch for all the clicks and every single table cell. So that way it's very efficient. We can save in a lot of setup and construction time and being able to avoid having to bind a click to every single table cell in a table. So in jQuery 1.4.2, so it just came out, we added a new delegate method in addition to the existing live method. So the delegate method works backwards from live in that you give it a route to work from. So this is an example I gave before in that find all the tables and then within the tables, watch for any hover events on a TD. So like I said, it works backwards. You would write this in live, you would say, find all the TDs.live hover. But the advantage to delegate is that it allows you to very easily hook to a lower part of the tree, okay? So in this case, we're attaching the delegation handler to the table instead, because in live, what we do is we attach it to the document because we don't know exactly where you wanna listen for the event to occur. So delegate is a way for you to hyper focus our attention to only look for events in a specific location on the page. So in this way, in some cases, delegate will be even faster than using a live straight up. And then of course, we have the live events. Something I should mention, in 1.4, we added live hover events. So this is something new. But just to show you an example here, so here you can mouse over elements and just to emphasize the way that live works is if you were to run this using bind, for example, the bind would only work on the elements that are currently exist on the page. But the fact that it's live, we can add in a new menu and the animation will work in that new element as well. It'll work on all current and all future ones. And it's just incredibly efficient that way. jQuery 1.4, we also added in a new helper method called proxy. Proxy is a way of changing the context of this of a function that's being called in jQuery. So for example, if you wanna attach a method of some object or some class, and you want to enforce that it's this is the original object and not a DOM element instead, because since in jQuery we override all handlers this to become the DOM element unless you use proxy. So this is very similar to like dot bind you see in a prototype. It's also in the new aquaScript 5 specification. The one difference between proxy and bind though is that you can attach a proxy, but then to remove the handler again later, you can just say object.method. The advantage to that is that traditionally when you're doing dot bind or something, you have to save that extra function you just created in order to be able to remove it again later. And that becomes a huge hassle. And so we take care of that for you. We're thinking of this one mentioned really quick. So jQuery actually has a whole bunch of ways in which you can extend the core library. There's the traditional way of writing plugins, but we also have a way for adding in selectors. So you can write your own custom selectors to find, I don't know, specific elements you want to match such as ones that are being modified by a plugin. In that way it's really quite easy. One thing that this is really old actually in like jQuery 1.2, but I wanted to show it because I love it and not many people know about it. So jQuery has the load method for loading in an external HTML page and injecting it into a DOM element. But it also has a way, so you see here after the file name is this H2. And what you can actually do is you can specify selectors after the file name. And what it'll do is it'll dig into the page that you just retrieved, extract those elements and then inject those as directly in. So this page actually has a bunch of elements on it, but when we hit run it actually just, it grabs the page, only grabs the H2 out of the page and injects that directly. So what I like about this is that you don't have to write any server side code in order to make this work. And so it's really quite empowering since you can just write this and you can just literally grab, wholesale grab and rip things out of pages and inject them into your current page. That's really quite excellent, yeah. So this is a single domain only. Single domain. Yep, and much of the, that load is always single domain since the problem is that, well I should say unless you're in a browser that supports the new XML html requests object which is currently only Firefox. So yeah. But the dot load and so we're retrieving HTML, XML, JSON, we're bound to only you define those browser limitations. The only exception is if you're retrieving JSON via JSONP or retrieving a remote script to execute. Those are the only two cases where we can grab from remote domain. So yeah, it's a bummer. I would love to be able to retrieve from a remote domain if the browsers gave it to us but we're bound to that by now. Probably for a good reason. So just very briefly, I wanted to just just to mention jQuery UI very quickly in case you aren't familiar with it. So jQuery UI is our collection of widgets and components that we work on. And these are, we've been working on this for a while now we're continuing to work on it, release new widgets. So we provide a whole bunch of really excellent components. So like a drag and drop and then all the way up to more advanced things like autocomplete and dialogue and things of that nature. But one thing that is really exciting is the jQuery UI theme roller. And the theme roller is, if I can, hopefully the internet connection is working, the theme roller is a way of customizing the look and feel of all your jQuery, all your jQuery UI widgets. And now what's interesting about this, so I just want to show you. So this is, I'm not sure how well you can see, but this is the theme roller and these are all different jQuery UI components. So like we have an accordion, we have a tabs, a date picker, slider, buttons, whole bunch of things. Here we have a dialogue, progress bar, et cetera. So in the theme roller, you can go through and you can pick completely different themes for styling these components. So if we didn't like this grayish theme, we could pick a different one and load up that theme. So we have a whole bunch of pre-built themes that go along with this. But what's even cooler is that you can actually dig in and completely customize every single aspect of these themes. So if you wanted to change the green header to, I don't know, something orange-ish, we could do that. And it's changed dynamically, but more interestingly is that it completely generates all the HTML, CSS, and images that you need to get this result. Working, and it even works in IE6 all the way up to modern browsers. So what I like about this is that I hate writing CSS probably as much as you do. So this is something to just be able to abstract that away and it takes care of all that for you, all the nasty cross-browser issues. So again, yeah, and all the images are nicely sprighted as well so it reduces the number of downloads. So everything is exactly as you would want it to be. So this is very cool, I like pointing this out since not everyone knows about it. And I always recommend it. Another thing I'd like to recommend is pulling jQuery off of a CDN. Now, a CDN stands for Content Delivery Network and it's really a way of saying a whole bunch of servers positioned all over the globe so that they're closer to your users wherever they might be retrieving the file. So jQuery is hosted on three different CDNs. We have, the jQuery project actually has our own, we actually have our own private CDN which we're quite grateful for. MediaTemple is providing that for us. That's awesome, we're abusing that very heavily. But Google also hosts jQuery on their CDN and Microsoft hosts it on their CDN. Google also hosts jQuery UI and Microsoft also hosts the validation plugin. So the nice thing about this is that not only are the files geolocated close to your users but all the files are minified and gzipped as well. So minifying and gzipping your JavaScript is the absolute best way of distributing your JavaScript code. What you do is, I should say, distributing the code for production. The first step is that you take your working JavaScript code and run it through a minifier. Some minifiers, we have like a Google Closure, or YUI Min, there's a couple of different ones. The jQuery project uses a Google Closure. We were able to get a 14% improvement over YUI Min using Google Closure. What this does is it strips out all the stuff that doesn't need to be shipped. Comments, whitespace, it makes all sorts of little file size optimizations before it ships the code down. So in that way, we can still write nice, readable code that you can read. But when we ship it in this minified version, it's nice and small. So we get the best of both worlds. And then on the server, you gzip your code. So in Apache, you use like mod deflate or any other modules or servers that you might use. And in that way, so that the file size is reduced even further from the minified state. So jQuery, for example, it's over 150 kilobytes uncompressed, but when we minify in gzip, it's only about 20k. So that's a huge reduction of file size. And especially considering, at least in the case of jQuery, how many thousands and thousands of times is being downloaded. So this is something, just a universal that I recommend to everyone to do with your code. I'll skip that for now. So I just wanna mention really briefly the sort of things that we're working on in the next version to jQuery. Right now, we're working on a rewrite of the Ajax code. This is gonna make the Ajax code much more extensible, allow you to write plugins to snap in new ways of doing Ajax transmission. We're also working on a way of doing dynamic script loading. So this is different from get script that we have now in jQuery. This is a way of additionally loading the scripts and doing dependency management. So this is something that we're working on. We're also working on native templating support. So a way of having some sort of templating language baked in, but additionally being able to write templating plugins so you can write your own styles of doing templating. And then most importantly, we're working on mobile support. So the big thing is that we want the current version of jQuery to not only work in all the current desktop browsers, but we also want it to work in all the current and most popular mobile phones as well. So what we wanna be able to guarantee is that if you have a desktop application working and you wanna load it up and have it see it work in your mobile phone, that it'll just work if you're using jQuery. We won't be able to make that guarantee for your CSS, but at the very least we can guarantee that for your JavaScript. So that is something that we're working on now. It's incredibly challenging, but we hope it'll be a very good result at the end. So we're not looking to ship a different build of jQuery. We're not looking to ship a WebKit jQuery or something. We just don't think that makes a lot of sense, especially considering that a lot of the original problems that existed with WebKit, for example, they had the issues with file size caching, a lot of that has been removed in later versions of the iPhone operating system. So at least for us we think it is the best use of our time to make sure that jQuery as it stands and as we ship it on jQuery.com, it will work just everywhere. Yes, jQuery touches something different. So yeah, so we're just making sure that the same core library will work and that we actively text against the major browsers. The big decisions that we're trying to make right now are figuring out exactly what browsers that we wanna officially support. So probably the hardest questions that we're trying to, so we're definitely supporting the iPhone, the pre, we're definitely supporting Fennec, the new Firefox browser. We're supporting Windows Mobile and the one that we're supporting Opera Mobile, not Opera Mini, since Opera Mini doesn't have JavaScript, it's gonna be kinda hard for us to support it. And the one that we're trying to figure out if we wanna support or not is the current version of the BlackBerry browser. Because the current version of BlackBerry browser is really bad and it has frightening bugs in it. But the new version of the browser is using WebKit. So we're trying to decide is it worth it trying to go through all this pain now. And yeah, I know people who are doing BlackBerry development right now and they're just like, why, why? So I'd rather try to avoid that. I'm just trying to figure out what the life cycle is like for the BlackBerry browser, so we'll see. Yeah. Okay. Yeah, so we're still doing all the capability testing. We won't be doing any browser specifically, but we won't be saying if WebKit, we're just doing BlackBerry. Exactly. So, and yes, we're gonna be supporting the WebKit, the WebKit builds on, let's just say the recent WebKit builds on Nokia. Oh, they're using WebKit then? Yeah, yeah. I thought they had them all. So, Nokia has a whole bunch of different devices and there's a very wide range in quality. So yeah, we're probably gonna support the most capable subset. So the sort of the problem that we're up against here is that when we target desktop browsers, we can very easily say, let's target 99% of all browsers because that's very feasible. But for mobile browsers, we may only be able to target like 75%, and even that's only maybe 75% of the smartphones. You know, I mean, so it's a very different world and we kind of have to take the dish that we're given here. So they're common JS stuff. I'm familiar with common JS and what they're doing. The problem with what they're doing is that it doesn't have a direct correlation to working in the browser. A lot of their stuff is expected to work synchronously and that just does not make sense in a browser landscape. In the browser landscape, you wanna paralyze everything. You wanna work asynchronously all over. And it just doesn't really make sense to try and provide an API like that, especially considering that we can get much better performance characteristics doing something different. So we probably won't be following the common JS API in that regard. We've had this URL for a while now. So jQuery.js, this is the unminified one. If you do .min.js, that's the minified one. I use that in all my projects. Yep, I'm trying to figure out a way of doing one even shorter. I think I might set up a subdomain for js.jquery.com and that'll just serve the minified one straight up. I think we also have HTTP. I think we also have HTTPS. So you can actually leave off the HTTP. You can just do slash slash. And that's what you can leave off the protocol. So if you want even less characters, you can do that. It's put in there first. You shouldn't be pulling from there if it's gonna break live sites. I mean, in that, if you're pulling from this that has no version attached to it, you gotta be ready for things to go. I mean, I do it in my code. But at the very least you, so we have a version specific. So the way we do it is we have, let's see here. No, just going up. So we have that, we have that. No difference. We used latest initially then I was like, why do we have latest? So you can point to specific versions of the code as well. The Google Ajax API, it's something like it's like jQuery 1.4.2 slash jQuery.js, something like that. And then you can say this, they get the latest version of jQuery 1.4. And then you can say this, like the latest version of jQuery 1. something. So there's no way to say the latest version for any version. So when jQuery 2 comes out, whenever that is, there's no, it won't transition up automatically. So there's a scroll back here, so it was. Oh. So performance wise, they're virtually identical because all this is doing internally is calling .css.ag class. I mean, it's not doing some crazy optimization there. So performance wise, you probably won't see any improvement. It'll probably be about equivalent performance wise. The only benefit I see to this offhand is simply that you could have an object from which that you're applying to a whole bunch of different things. And maybe you just wanna change this object in a slight way, but you don't wanna like have to write it all again. You know, it just, it makes it easy to reproduce. Yeah, so I mean, we've been talking about a way of doing like a data selector or something like that. There are actually a whole bunch of data selector plugins. So yeah, it's something we've talked about. We just haven't landed it yet, but it's definitely possible. We're hoping to get more people using the data API. And then once that happens, we can start to make better tools for it. So we don't have any automated ways of doing that yet. I mean, it certainly is a tricky problem since a lot of the things aren't necessarily quantifiable. Like you can look at the code and be like, wow, that's not the best way to be doing that. And then you can rewrite it. But one thing that we've been talking about, so we're working on a new plugins repository. And we're gonna be launching it here, hopefully within the next couple of weeks. And this new plugins repository, one of the features that I've been talking about is a way for members of the jQuery team to be able to recommend a plugin. So a team member can vouch for a plugin, say the validation plugin is written by Yarn, it's awesome, I use it everywhere, et cetera. So being able to at least lend our credibility, I would hope our credibility to be able to promote good code. So at least in that regard, we'll be able to do something. But at the same time, at least right now, we don't have any sort of way to be able to automate that. I don't think jQuery Lint, so I'll just bring up here. So jQuery Lint is a neat little plugin that came out fairly recently. And the idea is that you would run it in your code and it would sort of give you indication when you might be doing things wrong or you might want to, or maybe, it's sort of the linty type thing. I actually provided a hooks for that in jQuery 141, I added a new jQuery error hook, so it can hook into error messages that we throw. But yeah, I think it's a better indicator of your code quality versus a plugin code quality. Since a plugin doesn't necessarily always do things in the same way that user code might work. But yeah, yeah, jQuery Lint's cool stuff. I definitely recommend people playing around with it more so that we can get it better. So but I wanted to do a little bit of coding to hopefully better demonstrate the custom events and doing data attachments. So one thing I wanted to build to sort of demonstrate this is I have sort of a game. So let's, I'll pull up the completed one here. Oh, let's see. Okay, so it's really hard, especially with the trackpad. Let's show you, so these are people's icons here from the meetup. And so they're advancing and you have to try and click them before they come in. And the bigger ones take more clicks to destroy. And I'm really bad at it, especially with the trackpad, like I said, like it was Ben. So yeah, okay, so this is sort of the game. And what's happened is that the icons keep coming in and waves and the waves start to increase both in frequency and in rate and in the number of people that come in. And so I just ran out of lives and I was killed by a Zafar bag. So the core code to this, I wrote in a particular manner. Let's see here. All right, let's strip all this out. Okay, so can you read that okay? A little bit bigger. All right, so this is the code for the core of the game. The bit that makes the icons and has them trickle in. The interesting part to this though is that functionally, so let's kill that and let's, wait a second. Oh, sorry, I wanted to mention this really quick before the talk's done. So you guys obviously find out about the meetup on meetups.jquery.com, but there's, the UI isn't entirely intuitive. Like there's actually a jQuery Boston group in the jQuery meetups area. And it's, there aren't like, for whatever baffling reason it's not connected to the event. So right now there's actually, I think there's more people here than the entire jQuery Boston group. So if you aren't a member of the group, I definitely recommend joining it because then we'll send out updates and announcements to say, hey, we're gonna have to do a new meetup, et cetera. So definitely set up for that. Again, it's meetups.jquery.com. Okay, so go back to the code here. So to start, so what we have right now is just the core game logic. And it doesn't do anything. Hitting start does nothing. None of the actual gameness is working at this point. And just to show you what would happen here is, so if we look at the actual game logic, what we're doing here is we're loading in a JSON file of all the people. So it's all just name and icons, name and URLs. And then it's going through and iteratively adds in users. But the interesting part about it is that the game doesn't know to actually start itself because it's all done via custom events. So to show you here, so like we attach the game to the game element with an ID of game. And it's waiting for a start event to occur. And once the start event occurs, then it'll start to trickle in people. Additionally, it waits for the stop event. And when the stop event occurs, then it stops trickling in things and everything. But notice that there is no logic here for maintaining score, for maintaining lives, to actually handle you clicking and destroying things. Like the actual gameness of it is we need to write. The one thing here that we, so one event that's broadcast actually, is actually there's two events that are broadcast. Here we look for any time a mouse down occurs on one of the users that's coming in and we trigger a hit event, okay? So this way we can look for a hit event to occur and we can assume that that was the user attacking it somehow. Additionally, one other event that is put in is that when the animation completes, so it animates from the right-hand side of the screen over to the left-hand side. And when it finally exits off the left-hand side, then an escape event is triggered on that user. So there's the two events that are broadcast by the game, escape and hit, and it's listening for start and stop. So in this way we can hook in and really start to make things work. So just to show you here, we can pop them into Firebug and we could find the game and we could actually trigger a start event. That should theoretically start the game running. Yeah, so we triggered a start event and that was enough to tell the game to start trickling in people. Now, you see nothing's happening at this point. If we click on nothing happens, when they hit the left-hand side, they just stick there. They don't know to actually disappear or anything. So again, this is all, we have to write that logic. We have to snap that in. So in this way, it'll just keep going indefinitely. But here we can also stop the game. So we trigger a stop and then it stops, it fades the people out and now it's reset and ready to go again. So to start this, all right, let's see. To start running our code, we just start the way we start any jQuery code. We have our document ready or you use the shortcut passing into function to the jQuery object. But to start, what we probably wanna do is actually hook up the start button actually starting the game. On this page, there is only one input, so we can be really sloppy about it. And we can just say, when the input is clicked, we're gonna start the game. And then, yeah, we can just look for the game and we can trigger the start. So this is pretty simple, but we click this and it's gonna start and people will start trickling into the left. Excellent. So now, additionally, we can probably go through and probably the next thing we should do is we should probably start keeping track of score and life, okay? So what we can say, so we can attach the game and we can listen for a start to occur. Now notice what we're doing here. This is really interesting because we're listening for the start event to occur on the game. But remember that in the main game logic, we're also listening for the start event to occur. So this is sort of the ultimate benefit of using custom events and using events and triggers in this way is that writing custom events is a one-to-many way of doing code because when you write code in a class style, like you build a class and you say class.foo and you trigger some method on it, that's a one-to-one relationship. You have one foo, you're running one method on that foo and that's it. The nice thing here is that there could be any number of start events found to this game. We don't know how many. There could be zero, there could be 100, but all we know is that when the start is triggered, it'll run all of those. So this one-to-many relationship, this one-to-many way of running code ends up serving as a really efficient way to write complicated script and it's a good way of abstracting logic, particular blocks of logic from each other. Okay, so once the game starts, we're gonna wanna keep track of the score and the life. And then when the game starts, we'll reset the score. Okay, and then we should probably, we'll put that up in the little counters up there. See exactly what those are. We can use a firebug. They are ID of score, ID of life, incidentally. That's obviously, incidentally. Okay, so now when we start the game and we hit start, we see immediately that the life has been updated at the top and we're keeping track of that. Obviously, we haven't written anything to actually decrement the life or keep track of score. So we have to do that next. One thing you should probably do first is that the star button is still there. And so if we were to click the star button, we could start the game multiple times and it's about to get very complicated here in a second. As we see a whole bunch of them come in. So yeah, obviously we don't want that to happen. Okay, so we should probably hide the input button once the game starts. However you wanna do it. One way, you could probably do it differently. You could actually probably, you could change it into a stop button. You can stop the game. That could be another way to do it. I think hiding it makes sense since obviously then the user won't be tempted to do something with it. So yeah, we can hide it. And then additionally, we can launch for when the game ends. So we can bind for the stop event. So when the stop occurs on the game, we'll show the input again. That won't come into play until later until we actually implement stopping the game. So that's a good place to start. Now we should probably implement actually destroying these things that come in. Okay, so to do that, we remember that there's a hit event broadcast within the game. And the hit event is broadcast on the users themselves. So what we can do is we could use live events for this. We could say watch for all the users and watch for a live hit. So this works like live events work with custom events as well. It just works completely gracefully. So this way we can say watch for any users that come along that get hit and we will do something about it. So we actually attach inside the game logic itself. We actually attach some information. So here we're constructing the user. The user is a div with an image inside of it. But additionally, as you can see, we set the dimensions. But we actually attach some data to it. We have data for hits, max hits, and user. So user is the name of the person that's coming in. So we can actually use this information to this data attached to the element to see exactly how many times it's been clicked. So because what's happening is that, remember how the little guys that came in, they took one click to destroy them. And the large guy took a whole bunch of clicks to destroy them. We can monitor those numbers through hit and max hits. Okay, so to get to that, so what we can do is we can get the data off of the user. So we added this in a jQuery 1.4 where you can say just dot data, no arguments, and that will just return the entire data object associated with that element. And what we found is that this is actually much more efficient than the traditional way of getting and setting data through the API. It ends up being a lot faster. So when the guys clicked, we wanted to increase the score. We want to increase the score by 100 and we'll want to increase the number of hits the user we just clicked. So what we need now need to determine is if we've clicked it enough times to actually weren't destroying it. So we can say is if the number of hits is greater than or equal to the number of max hits. Because that was put in by the actual game logic there. So in this case, we can actually destroy it now. And so first thing we should probably do is we need to stop the animation of it moving across the page. So we use the jQuery stop method and then we can just remove it. Doesn't have to be a whole lot more complicated than that. But if enough wasn't done to actually weren't removing it, we could probably get some indicators. So the only time that it won't actually be removed in that first click is in the large guy. And if you notice that when we clicked the large, well actually you didn't notice because it didn't happen. But when you click the large guy, the border turned red around it. To do that in the CSS, it is hit. We add a class of hit and the border turns red. So we'll say, so if we didn't bother stopping it, the animation will continue. It would be continuing on an element that isn't in the page anymore. So, ideally, the thing is that, yeah, removing an element from the page isn't enough to just stop the animations that are running associated with it. Since I guess presumably, you can start an animation or something, remove it from the page and then later on insert it back in to have the animation finish. I don't know why you want to do that. But yeah, so we'll just stop the animation and then we'll remove it. So let's see. So we increase the score. Oh, and we need to display the updated score. Okay, so let's reload and we'll start the game. So the button highs, you get score zero, life 100. And if we click a guy, the score went up and it was destroyed. And the score is actively continuing to go up and it's going really fast. And there goes Ben Allman. So we click Ben once, he turned red. You have to click him a whole bunch of times in order to actually destroy him. And there's Al. So we see that that logic is working then. That for many users, we only have to click once. But note that the life isn't going away. And note that they're actually all just kind of stuck here to the side, since we haven't actually removed them from the page yet. So yeah, so we got to, we have to fix that. Okay, so in order to implement that logic, we remember that there's an escape event broadcast as well. The escape event is just like the hit event, it's broadcast off of the user that's traversing across. So we do the same exact thing. We can say, look for all the users and watch for a live escape event. Okay, so once we're in here, we're gonna do something very similar. We need to first, we need to see how much damage it's gonna do. And the way we would determine the damage is, so the small guys are just gonna do, well, the small guys are just gonna do a minimal amount of damage, like three. And the large guys are gonna do a lot, like 15. So the way we can do that is we can, since we have the data, you can access the data again. And we can actually figure out how much life we wanna remove and we can just multiply it by the number of max hits. So we can say max hits, since max hits for small guys is one, for large guys it was five. So we can say max hits times three. And that'll decrease the life. Let's make sure it doesn't go below one, since that would look weird. So we say life less than zero. And we can update the life counter. Okay, so that'll update it. And now we can work in the logic for actually when the game ends, since the game is gonna end when we have no more life left. So we can say if the life is less than or equal to zero, well, I guess we could just say if it's, well, yeah, less than or equal to. Yep. And we can probably, we can trigger, if you remember back in the beginning, we can trigger the stop on the game. And so that will trigger, that'll tell the game logic to stop doing what it's doing. And it'll also tell the input to show again, the button to show again. So we can start the game over. So let's give that a run. So we hit start. The critters are coming in. In this case, we wanna let it keep going and keep damaging us so that it will die. So okay, so the life is actually decreasing. You can see the life counter going down. And we're gonna get dinged here pretty bad here in a second. Oh, one thing we've noticed that we forgot to do here is that the guys aren't actually disappearing. They're still stuck to the corner. We can figure and fix that here in a second. Actually, while we're waiting for those guys to come in, we can do that. To remove the guy, we need to say dot remove. And that will remove them from the page. Oh, there we go. And there we go. So the game ended. Everyone with everything that's there fades out. And notice that the start button came back again. So we can start the game over again. Wait a second. Well, no, we didn't reset the score. Well, it would reset the score once we hit start again. Yeah, presumably if I clicked one guy, we would have had a hundred points and that would have been obvious. But okay, so we got to remove the people once they hit the left-hand side. And we should also show what person actually destroyed us. Cause it's funny. So we have the stats paragraph and we can append on, do we need to count? I think I have to give it a class because I have some styling. And then, so since we have the data object here and the data has the dot user property and the user contains the name of the user that we attached on. I think that's what we want. Did I close everything off right? Which I, okay. Some people will tell us sometimes ask me why I use like B elements instead of strong cause I like it, I don't know. I love using center still. It breaks my heart that that's gone. I love center, I love B, I, U, S, S for strike through. Those are all great elements. I'm never getting rid of them. It's no for forever. All right, so let's start the game going here. All right, so we'll have a score and so we'll just wait a couple of seconds. We can watch the damage start to come in. All right, so you see the guys are actually moved now. They hit the left-hand side and then they go away which is exactly what we want. They don't, they shouldn't have to stick around forever. So, you're gonna take damage really quickly here once the big guy started rolling. Yeah, we don't have long now. And done. So you're killed by Austin J. Alexander and fades out. So we have a score of 100, life is zero. And if you want to start a new game, we can just click start again. And in the next batch, we'll come in. So we should probably remove the name of the person there. So we can just say, let's see, on game start, yep. We can just, we can look for the, B, the classic kill and remove it. And that'll remove the, that'll remove who killed us at the start of the game. And we're about to die again. All right, so let me, I also have, so I also have a copy online. Let me exit out of that one real quick. Let me find it. Cause I'm sure some of you will probably want to try and play it. So here it says. So I have it online here. This is the completed version and it should work. Yep, sure, how we would. Yeah, yeah, yeah. Wouldn't that, wouldn't that make more sense? Sure, sure. Yeah, so yeah, we could do game delegate user hit. Yep, that would have the same effect. So the difference between the live one and what this is here is that the live is listening off of the document. So it's looking for any hit and any escape happening anywhere on the page. Here it's only listening for any, any escape from that game, which is probably better anyway, since theoretically there could be another game on the page that's doing other hits and other escapes. But yeah, I mean, in general, it's probably a better idea to keep it in close like that. So I'm trying to remember how it happened to Jetpack. But if it's anything like how it's done in like iframes and stuff, you use the post message API. So JQuery does not attach into the post message API. Well, that's an interesting point because that could serve as a way, like if you try to trigger an event on a document that's in a different domain, we could say, actually use post message, communicate with the other JQuery process on the other side and then trigger that event on the other side. I think it was to see that as a plug-in. Just as a first go, yeah. But JQuery does not have that baked in. Any other questions? Yeah, so like in remove, like whenever you call it out remove, we would remove all the events and all the data attached to an element. If you want to get a reference to the element that has everything still intact, use dot detach. We added dot detach in JQuery 1.4. So that gives you the elements with everything still on it. So now that I actually, now that it's doubled across the issue with the animation still happening, but even after it's been removed from the page, maybe we'll just kill off animations when you remove it from the page as well. But just believe them running if you do dot detach. So JQuery stores that in, so JQuery has a property called jQuery.expando. And so like on an element, so if you had some element and you said a jQuery.expando, that would give you the unique ID. But that would only give it to you if there is a data store attached with it. We remove, we clean this up if we don't have any data store since we don't want to have this expandos laying around everywhere. So that's one way to get it at that unique ID. Yeah, any other questions? I guess I think we were gonna do a raffle. Because if we have some books. But I just want to again remind everyone to definitely sign up for the actual real JQuery Boston Meetup Group since then we can actually see each other again, which would be nice. And so we have the books donated by PACT. And they're very excellent. This is the jQuery 1.4 reference guide. Yes. Yeah, that's all you got.