 Good morning. Good to see people on time. Appreciate that. As promised, we're going to get started. Doesn't matter who shows up. It's nine o'clock, so we're going to get started. I would like to invite our next keynote speaker, Dave. Dave is the president of jQuery Foundation, and he's also the lead developer on jQuery core project. He's a guy who knows his shit, so let's welcome Dave to come and enlighten us on some of the mistakes that we should not be doing. With not just jQuery, I think he's going to go a lot broader than just jQuery. So over to you, Dave. Thanks for coming. All right. All right. Yeah, I tend to wander around when I speak because I get wrestles up here, so I decided I would get a mic and let me move around and not keep me tethered here. I'm really glad to be here and keynoting for the beginning of day two. I hope you all had a great day one. I did. I saw some really interesting presentations, so some of them actually tied in pretty well to many of the things I'll be talking about today. There's a lot of amazing things you can do with jQuery. It's very powerful, but like many powerful things, you have to be careful because sometimes you can hurt yourself with power, and that's true of things like chainsaws or electric drills or in this case, a gun. And so the analogy that because of course Americans are gun happy, the analogy that we often use is to shoot yourself in the foot. So the idea of a gun is supposed to be to defend yourself, but more often you end up hurting yourself than someone else. So these mistakes are really like shooting yourself in the foot. You want to know enough about how to use jQuery effectively that you don't do that. So you're also going to find out some really interesting, weird tricks about how jQuery works and in the process become a much better jQuery developer and in general, a better JavaScript developer because many of these things are not problems specifically with jQuery. They're issues with the way JavaScript works inside of browser. So jQuery 1.0 was released almost 10 years ago. In January of next year, it'll be 10 years. Now when you think back to what web development was like 10 years ago, it's almost impossible to think back how crude and primitive things were back then. Things have gotten a lot better and things have changed quite a bit. And the best practices that you use for writing websites have changed. So those little animated gifs that you used to use for, I don't remember if you knew, one of my favorites was the hand coming out of the website. I don't know if you remember that one was grabbing at things or the little animated, send me email icon. Those have kind of fallen out of favor or of course everyone's favorite under construction. You don't see those very often anymore. The performance bottlenecks differ a lot from the way they did 10 years ago. JavaScript has gotten much faster. Used to we think of JavaScript as a bottleneck. It's really not a bottleneck anymore. Now the document object model has also gotten faster but we've given it so much more to do. If you think about the features that we've added to HTML and CSS in the past 10 years, we've added these complex HTML5 elements that have their own user interfaces. We've added things like CSS gradients and animations. All of these make the job of the browser even more difficult than it was before, especially when interacting with your JavaScript. So the good news is though that web development is evolving. We're making it easier, hopefully, for people to write web pages with less of the tedious code. That's really what jQuery is about. But unfortunately for most web developers, change often means break. It's very difficult to change the way things work without breaking the way they used to work. I'm not just talking about code. Code and plug-ins are two obvious ones, right? Like a new version of jQuery comes out and your own code needs to change or you have to get an update to a plug-in so it will work. But there are also things like bad programming habits. The reason why web development has changed over 10 years is because there were things that we used to do that we have all come to discover were not really good ideas, things like browser sniffing. So we want to break those bad programming habits. But another more subtle thing is we all learn by Google, right? We go out and we say, I need to solve this problem. How do you solve this problem? I need to find a plug-in for it. I need to find whatever. And so those documented best answers that you see on Stack Overflow or on somebody's blog post, those may not be correct anymore because when we change jQuery or when best practice changes on the web, that 2011 blog post just may not be the best way to do it anymore. But then if you don't change things, how do you stop people from doing the wrong things? If you don't make that change, then how do you stop people from doing the wrong things? It's almost impossible. Now a lot of times people will come back and they say, well, can you just do something inside jQuery to make this work right so that I don't have to go through the pain? And we actually found what we think is a pretty good compromise solution. In jQuery 1.9, we pioneered this by coming up with something called the jQuery migrate plug-in. And what that does is you use the new version of jQuery along with this plug-in, and then you run your web page or your web app, and it identifies through console errors, console messages, what it has seen this code doing that it knows is not really supported by the current version. And it also, in many cases, can make it to the old behavior works correctly. So you can run jQuery migrate with your own code. You look at the list of warnings it's giving you, and you can go back and fix your code or go find the plug-in update that will solve your problem, or maybe even switch plug-ins. But you can also use jQuery migrate for a long period of time. I don't recommend that. And that's why when I say fixing the rest is up to you, it really is worth reading the error messages and the warnings that you get and fixing the code rather than just saying, well, I'll just always use jQuery migrate. Really, migrate is intended to be a crutch and not intended to be a long-term solution to your problem. So there are some changes coming in jQuery 3.0. We talked a little bit about these yesterday. Deferreds are going to be promise A compatible if you're familiar with the promise A spec. The most important thing from a practical sense is that that changes the behavior of errors. Today in jQuery, if you use Ajax and an error occurs, it throws a message on the console. If you're using promise A promises, you won't see any error whatsoever. And it's very important to use catch on a promise chain to make sure that you handle any error even if you don't think an error will occur because that's when they always occur, is when you don't think they will. And there's also a big change coming that we hope we can make stick regarding show and hide. And I'm going to be talking about that in detail a little later. But let's talk about some other foot gun problems that people have had with jQuery in the recent past. One is jQuery latest.js. Early on in jQuery's evolution, someone said, you know, it would be really handy to have a place where I could go and get the most recent version of jQuery so I could download it to my own site and use it there. And so John Resick said, this is great. Every time we release a new version, we'll just copy it to this jQuery latest.js file. And we'll even have a minified file. That'll make it really easy so that you can just make your own copy of that file. Well, unfortunately, what some people did is they said, hey, this is wonderful. I can use the script tag to always run the latest version of my site. Now, when you think about what that does, every time we release a new version of jQuery, it will change the version of jQuery that runs on your site. That is a version that you probably have not tested with. You have no idea whether it works with your site. But because you have directly linked to jQuery latest, you have now possibly broken your site for everyone who comes and visits your site. Now, that would be a limited problem, except think about all the websites that are created in the world and really never maintained. So these sites get created by somebody with the best of intentions and it's like the Space Jam site, which was built in 1996 and it's still there and it still works. And that's really what we all aspire to do. We want to build something that lasts forever, not something that lasts until the next jQuery update. So what happened is we started getting error reports from people and people were saying, I got the latest jQuery and it destroyed my site. What's wrong with your people? So we said, well, this is going to be a problem in this case. Someone actually noticed and hopefully they changed their site. But in the general case, we can't do that. I mean, we can't go and change someone else's site. So we got together with the Google people because they saw the same problem happening with people who were using the Google CDN with a non-specific slash one. And we agreed that we were going to freeze the jQuery version at version 1.11.1. That version will never change anymore because what we were finding is as time progressed, we were breaking sites and this essentially says latest is now always going to be the same version. And the reason we had to do this is because there were too many people in the wild using jQuery in a way that broke their own sites and we had to protect them from themselves. So my message here is really never use jQuery latest anymore because it doesn't mean what you think it means. So always include a specific version of jQuery. Always test your site with that version and only upgrade jQuery or your plugins for that matter when you have the time to retest. So I have no problem with your website that you built two years ago using jQuery 1.9 because that's when it was built. If you're starting a new site, I advise you use the latest version of jQuery. But don't feel like you have to just always go and upgrade jQuery because when you do that, you always should retest to make sure that all of the plugins that you're using work with the latest version. So we talked a little bit about jQuery 1.9 and even though it's been a couple of years now, many people are using older versions than jQuery 1.9. And two of the things we removed there were dollar dot browser, which was using browser sniffing. And this was an example of something where we said, this is an extremely bad practice. We had marked it as deprecated since jQuery 1.3, which I think was 2008. But we kept putting off removing it because people would always give us some obscure reason why it was important. But we finally did the right thing and jQuery 1.9 took it away. There was also live and live was overused. And in particular, one of the reasons why we removed it is because you have to be very careful on Apple touch events that things don't always bubble the document. And so when you're trying to build something, you may test it on a desktop machine and it works fine. And then you get to testing it on an iPhone and it doesn't work. So we wanted people to think specifically about whether they wanted to use something that bubbled to the top of the document. There's also a performance issue there, where anytime you let something bubble all the way to the top of the document, it is slower than if you could handle it closer to the point where the event occurs. And again, the jQuery migrate plugin is going to be able to help you with a lot of these problems. Because anything that we took out of 1.9, just I believe everything that we took out of 1.9 is handled by the jQuery migrate plugin and will help you find any problem if you're out there trying to upgrade an old site that's using jQuery 1.6. Now, there's certain things that jQuery does for you. And then behind the scenes, it's doing some ugly work. It's not just a single barrel foot gun. You can shoot both of your own feet and two of your friend's feet, I suppose. It's amazing what the browser has to do. In 16 milliseconds, this process occurs. When you make a change in JavaScript and it affects the HTML or the DOM, the browser has to create a new render tree. It lays out that render tree the way it's going to look on your infinitely scrolling page, and then it paints it onto the screen. And all of that has to happen every 16 milliseconds, ideally, to get a very smooth flowing animation. If you do something that takes a lot of work, either by the browser or if you do something in your JavaScript that takes a lot of work, you'll create something called jank. It just makes the browser stutter. And you've probably seen that either in jumpy animations. You might see it when you try to scroll a page and it just seems to get stuck for a second. All of those are signs of jank, and they're signs that you're trying to make the browser do more in that 16 millisecond frame that can really be done. So there are a couple of selectors and methods that in particular can cause some problems with that 16 millisecond window. Two of them are visible and hidden selectors. So if you're familiar with them, they are custom selectors that you would use them just like you would any CSS selector, but they're special. It essentially says, find me an element that is not only whatever else I ask for, but it has to be visible in the document right now, which means it's not display none or a width of zero or a height of zero. And the converse of that is hidden. So to answer the question if something is hidden or visible, we have to go back and ask the browser, because the browser is going to process every 16 milliseconds and it will be able to tell us when it figures out the layout, whether this element is visible or not. Now that could be a problem, because let's look at a simple example. Let's say in a high frequency, like a mouse move handler or a high frequency timeout, we're doing something like this. Maybe we don't do it every time, but in some case we add a class, we remove a class from the body, and it should say add class there. And then we look for visible selectors, visible paragraphs, and we're going to color them blue. This isn't exactly the code that I came across, but it's similar to it. So it's a very simple thing. We're just changing the class on the body, and we're going to mark some elements blue. But we're going to mark them blue if they're visible. So I'm going to add something called console time. It's a really interesting API that you can use the browser tools with their timeline feature and actually see the amount of time it took to run a series of code that's in your own application. So here's what it looks like. This is in Chrome. Those two lines of code took 30 milliseconds, which is a pretty long amount of time. If you recall, I said it, 16 milliseconds is ideally what we want to never exceed if we want to keep our page from being janky. And when you think about the extra amount of overhead there is in the browser trying to do something as well. We are past two frames worth of effort here for the browser just to tell us whether some paragraphs are visible. And the reason why that's true is you can see this recalculated style takes a huge, huge amount of time. And the reason it takes a huge amount of time is because we had to add a class to the body. Well, all the paragraphs are under the body. And that means that the style we added to the body potentially may have changed the visibility of those elements. And in fact, one of the nice features you get out of Chrome is this yellow triangle. When you see that on a Chrome timeline, it's telling you that some piece of code below this has forced layout. Now this is where jQuery gets blamed for a lot of the sins of the world. You can see that jQuery is named at the scene of the crime here. But what really happened is we called add class, or you called add class, so jQuery added a class, and then later an event happened that forced an event, that same event, forced layout by asking for the width of an element. The reason why it asks for the width of an element was because that's the way visible is implemented. It says, is the width of this element zero? Okay, well then it's visible. So something as simple as those two lines caused us to lose two whole frames. So let's use a class instead. Instead of using the visible selector, I'm going to use a class called showing. In the case where I saw this on a client site, we could add, they were actually tracking these things themselves, and we could easily add a class called showing that would show, say these paragraphs needed to be showing. Well wow, look at that. Instead of 30 milliseconds, now we're at eight milliseconds, only half a frame. So we've increased our performance significantly, we've gotten rid of the jank problem, and all just by making a very, very small change to the code. So this is where I'm, we're knowing the way the browser works, and what it does is very important to getting the best performance out of the browser. So I always, I always have a problem of trying to explain to people, depending on how well you understood what I just went through. Some people will come away with the idea that visible and hidden are just horrible selectors and they shouldn't be used. There are times when they can be applied to good effect, but what I found is a lot of times people don't know when those best times are, or they never come back to profile the code to see what the effect is. So sometimes the easiest thing to do is just to avoid them all together. But in particular, for this case, don't use classes on elements for things that aren't presentational information. Sometimes people will use classes as kind of global variables for their JavaScript. And that's not a good idea, because when you do that, you can sometimes make the browser think that it does need to do a new layout, because you've added a flag to the body that really nothing changes presentationally because you added that class. It's just a flag to some other piece of code to tell it that you've done something already. So don't use classes for JavaScript-related state. You can either keep that in JavaScript only, or if it's something that does need to be kept on the document itself, use data attributes or jQuery's data method instead to store that data, rather than class names, which really should be as much as possible saved from presentational data. And that will eliminate the problems that you might have with forced layouts. Now somewhat related to that, you show it hide. And I mentioned in jQuery 3.0 we're looking at making a change here. So it seems like it should be really easy. Show makes an element visible, and hide makes an element invisible. And then today we change the element style attribute directly on the element to make sure that it sticks. So we don't use a style sheet or anything like that. I guess if we were really picky we should try to set the important attribute to make sure it sticks. So what possibly could be wrong with that? It seems like such a straightforward API. Well, here's a few examples. Not all of them, but just a few of them. What about detached elements? What does it mean to create an element outside a document, to show it, and then append it to the body? Since the element doesn't have a hidden attribute on it or a display none, do we need to do anything here? Or can we just append it to the body? Well, obviously if it was initially hidden, then we would have to do something. We would need to set display inline, right? We would have to make sure it's showing. But what if the parent is hidden? Well, we can't do anything about that. We can force that element to be display inline, but we can't change it to be visible because the parent's hidden. But what if the display of a span is not inline? What if it's blocked and we append it to the document? Well, if we set it to inline, we've broken the page. What about responsive pages? If I have a style sheet that changes the display of an element based on the orientation the page is in, then if I use show, I forced it to a specific display orientation and whatever I did with my media query doesn't apply anymore. And that's actually not all that uncommon, especially like in menus and such, maybe use display inline for one orientation and display block with them stacked under each other for a different orientation. So all of these things kind of interact to make show and hide much more nuanced than you might expect them to be. And people will sometimes will say to us, well, why should you change working code? I mean, yeah, show and hide are kind of weird, but why would you want to change them? Well, some of the cases that we looked at there are still broken today because we can't really reliably determine whether an element is blocked or inline or what's going, we don't know when you create an element outside the document in particular, what the document's going to look like when it goes there. So that's a problem. The most serious problem as far as best practice is concerned is our currently working code forces layout. So to determine what the current display type is, we actually have to do some kind of crazy things to the document to say, well, if we were to put a span in this document right now, what would the current display type be on that span? And that way we can try to set it to the right version when you show it again later. That's a serious problem, especially on large pages, because when you're dealing with thousands of DOM elements and you're going to show 10 or 20 of them and we're having to go in and jigger the page forcing layout, that can cause various, very serious performance issues. We saw one that Paul Irish from the Chrome team pointed us to, it was in Wikipedia, and this page had a lot of other problems. It wasn't just a jQuery show and hide problem, but their editor took 13 seconds just to initialize when you load the page. So, you know, our goal is to try to make sure that when you use an API in a way that seems somewhat reasonable, then you get results that are somewhat reasonable, and right now show and hide don't seem to really fall into that category because people don't expect some of these crazy things to occur because they're not looking at the boundary conditions. The solutions to this, as I mentioned, we're looking at some possible solutions in jQuery 3.0. A lot of those will involve changes that break existing code. I think the best way to handle this, from your perspective, when you look at how you're going to design jQuery code today, try to use classes to show or hide elements. Don't use show and hide. Just have it put a class on the element, and that class can have display none, or maybe it's got a media query that goes with it so that it changes display properties based on the size of the screen. This allows us to avoid edge cases with forced display types, non-default display types, and lets us avoid the stuck, the forced layout problem, and that way elements also aren't stuck in some state if you are using media queries. That makes it work with responsive design. So I thought this was a very cute tattoo, a gun on a foot, another take on foot gun. See, this is what's great when you start doing image shows, you just find everything. This is an Ajax foot gun. Okay, what does it look like this code does? It looks as bad as straightforward as you could expect. I'm going to get file.txt from the server, and when it comes back, I'm going to alert out the data that I got from the server. Okay, nothing could possibly go wrong. In fact, that's why I didn't bother putting an error handler in here, because clearly there's no reason for an error handler. So disregard what I said about needing to check for errors before. Well, a lot of things can go wrong. Imagine if I, there's a method called Ajax setup, which lets me change the default parameters for Ajax requests. So some very cruel person has said, well, the type is going to be post, and the data type is going to be JSON, and the timeout is 500 milliseconds. So when you do that, the chances are that your server, this will fail in so many ways that you'll never get this request to succeed. First of all, when you send the data, you're going to do a post request now, rather than a get request, which is probably not what you meant to do at all. Also, when the data, if it were to come back, the data type is JSON. So unless that file.txt has JSON, when it tries, when jQuery tries to parse it, it's going to throw an error. But let's assume the file had JSON in it. The timeout is 500 milliseconds, unless the server is very close to you, it's probably going to take more than half a second to reply. And when, so in any of these cases, you're going to get some kind of error. And you could literally spend your life trying to figure out what went wrong. Now imagine if you're writing a big application, and you've got one group over here that is, you know, that is responsible for one thing on the server, and they're making AJAX requests, and they go, well, these are the defaults we want. Obviously, we always are posting, and we want to get JSON back, and we need a really short timeout, because if it doesn't happen quickly, we just want to give up. You, on the other hand, are on the other side of the building, and your job is to just make normal requests, and you're looking at the documentation for jQuery and going, well, the default is a get, and the data type is intelligent gas, which on a text file would probably be text, and the timeout, there is no timeout, it waits forever, which is exactly what you want in your case. Well, you are the losers in this scenario, because your requests are going to be paying attention to the global AJAX settings. Global settings really are a big mistake that we made, because it's impossible to tell at the point where the AJAX call is made, what the code really does. They contradict the documentation. So really, you know, if we wanted to make our AJAX documentation even longer, every place that we talk about a parameter, we would go data type. The default is this, unless you set it in global AJAX settings, in which case all bets are off. You know, every one of these parameters could be set in global settings, and essentially change the way jQuery works. It makes it very difficult for plug in writers, because the plug in writer, as a defensive measure, has to specify every setting they think could possibly be changed in an AJAX request. Otherwise, their code could break. So I would definitely advise don't use AJAX setup. Now, you're probably thinking, but I want to call AJAX from 100 places in my code. That may be a code smell right there, but if you say, well, I want to call it from many places in my code, and I need to have the same set of parameters that I want to have to type them in every time. Well, obviously, there's ways around that, right? You can just have your own command, like in this case, you can set the default parameters, and then just have your own function that you call, rather than calling AJAX directly. I think that from a semantic standpoint, like I called this with a remote command, because I'm thinking that it's probably making kind of a remote procedure call, that's a better way to do it than calling AJAX the raw way anyway, because you're kind of defining logically what you want to do rather than just making a direct jQuery call. So, jQuery, I think that as far as the API confusion goes, the dollar sign constructor, well, AJAX probably comes in first, but dollar sign comes in second. This constructor takes everything. And let's see how many of these you know yourself. Okay, so this, that's document ready, right? You put a function in the dollar sign, and that means when the document is ready, execute this function. This wrap, say, a DOM element, so that's, you probably use dollar sign this all the time, right? And in most cases, in like event handlers, dollar this would be wrapping the element that the event occurred on. You can pass an array of document elements, of DOM elements, and then that becomes the collection. You can pass a jQuery, you can pass a plain JavaScript object. This is kind of an obscure and not super well supported signature. You can pass a single element, like in brackets div, and then you can set a list of attributes. Again, this is kind of an obscure one that I don't particularly like, but it's there. You can have a selector string, and you can have HTML. Any of those, basically you can pretty much throw anything at dollar sign, and it'll give you something back. It won't always make sense, because I mean there's also ones like null and undefined, or empty string, and those, those create an empty set, or just nothing, you know, dollar per end per end is an empty set. So it takes a lot of things, and it takes a lot of non-things. That makes it a somewhat dangerous method. You have to be careful about what you pass to it. That's particularly true when the code might be trying to entice you into making an interpretation that's wrong. So in here you might say, oh well obviously somebody's selecting an element out of the current document, and appending it back to the bottom of the body. But then selector is just a variable name. Selector could be any of the cases that we looked at before. It could be a function, or maybe it is a select, maybe it is a string, it's a selector, but what if it's actually HTML? Well that would be bad, right, because it doesn't have to be a script that alerts 42. It could be a script that steals cookies or destroys the page, or whatever it's doing, likes somebody on Facebook. I mean those are the typical exploits that you'll hear about is the ones where somebody will inject something into a page, and it makes you like them on LinkedIn. JQuery APIs insert HTML. That's what they do. That's what they're supposed to do. So sorry about it being a little dark there, but use JQuery to manipulate HTML. It's not a bug that JQuery can manipulate HTML. But it can be a significant foot to have done if you're not careful. HTML can have scripts. The scripts will execute when you inject them. If you're doing things where you want to change something on the page, and it only has text, then use .text, not .html. I think a lot of times people use .html as kind of their go-to method for changing anything on the page. But you have to remember where you got the content from. So don't blindly trust any data that you got from the user, from the URL. You have to even be careful about round-tripping data to the server, because you can imagine situations, for example, where the user fills in a form, submits the form to the server, the server returns that data to you on the page at times, and that page, that data they typed in could have HTML, or the data that some other user saved into the database could have HTML. So this is a, it's a significant problem that's much bigger than JQuery, but it's something that you need to remember when you're dealing with JQuery, that when you manipulate HTML, you have to be very careful about where you got that content from. Another classic one, which we actually closed in JQuery, we closed this in JQuery 1.7, but document.search is the part of the URL from the hash over. So if you use the hash, that conveniently is also an ID in a selector. So people will use this kind of shortcut and say document.search, add, and then they'll do something with it, like add class selected would highlight whatever ID, whatever hash they put on the URL that they just went to. But there's no guarantee document.search is just a selector. It could have HTML because it was on the URL, and you don't know where the URL has been. It might have been, it might have been modified by an attacker. It might have been a link that the attacker got a user to follow and then injected script. So if you're not careful with the way you use JQuery, if you're not careful with the way really you design your site in general, you can get yourself into some really big problems with cross-site scripting. Okay, so let's go to some things that are a little less catastrophic, but still something that will make your code better if you follow some of these rules. A lot of times when people start using JQuery, they always want to do every line of JavaScript of JQuery away. And that was never really the intended use of JQuery. When you think about when JQuery was created by John Resig ten years ago, every programmer at the time used plain old JavaScript with sometimes with some libraries added. And they were very familiar with JavaScript. They were very familiar with the document object model. And because of that, they were very comfortable with using DOM elements directly. And in fact, you see the results of that when like an event handler that this value is a document element. It's not a JQuery object. It's a document element. Now, John could have said, well, you know, let's just make that a JQuery object. But it actually was more efficient and more comfortable, especially for developers at the time, to make that a DOM element. So here we see a case where we want to toggle all the checkboxes in a collection. And doing that, we go through and we change the property and the checked property. Well, you could certainly do it this way. You can see it's kind of, well, it just is ugly in a lot of different ways. It's ugly because there's lots of punctuation characters. And there's just a lot of duplication in there. You can do it just as easily this way. Just use the check property directly on the checkbox. That works everywhere. And you can see it's a lot prettier. You're still using JQuery, but you just don't need to use it to access. And it turns out there's a lot of cases like this. So there's the check property. Actually, this is checked. It is even more of an abuse. I guess people like it because it reads more like English. But this, these cases run roughly 100 to 200 lines of JavaScript code to do what they do. And this, of course, these are all one line. So it's about a 200 to one ratio. Now, in most cases, none of those are time critical, right? When you're toggling a checkbox, whether you run one line of code or 100 or 200, usually it doesn't matter. It won't make your site that much slower. But why run 200 lines of code when you can run one? And you can see it's, it just looks better. It's shorter to type. And there's, in the same way, there's a lot of custom selectors that jQuery has that we've added. We've mentioned a couple like visible and hidden. They extend the standard CSS selectors, but they're not supported by query selector all. Now, what that means is that we actually have to use our sizzle JavaScript engine to parse and execute that selector. And that makes things a little small, a little slower. But in general, speed is not the main concern there. In the visible and hidden case that we looked at, the fact that we're going through sizzle is not what makes this slow. What's making it slow is the fact that we have to ask the browser a hard question, and we have to go through the little jeopardy music while the browser figures out the answer. So we want to try to avoid, whenever we can, these old custom selectors that don't really add that much value. And the ones I'm talking about here are ones like colon checkbox. Yes, input type equal checkbox is a little longer, but query selector all knows about it. The same with colon button, which I always forget when I've seen people use colon button. I always forget that it includes not only button elements, but input type equal button. So it's a little bit confusing sometimes that you actually have to look up or memorize the definition of these to know what each one of these does. First and last in particular, those sometimes don't do what you think they do when you're dealing with multiple, the children of multiple elements. So first child and first are better options in many cases and more obvious what you're doing. Now, I do want to point out there are cases where it's not a good idea to use native methods. So you've probably seen the you may not need jQuery crowd talking about how you never need jQuery. This is actually a couple of examples of where you can get into a lot of trouble if you think that you can just use native methods for everything. You saw a few cases where I said you should. Here's a few places where you have to think about the level of browser you want to support. This first example here does not work. There is no class name. There is no class name object on a DOM element in IE 8 or Android two point anything or for that matter on. I'm blanking what's what's the headless browser of phantom. Yes, I meant class list. Sorry. I meant class name at the bottom. I meant class list above. But class there is no class list on IE 8 Android or phantom and a lot of people use phantom for their testing. I really hope 2.0 phantom comes along sometimes soon. But right now, if you have some headless tests that you do, they'll break if you start using class list instead of add class which will work everywhere even on all of those browsers. Now, there may be other solutions that you can use. For example, if you can assert that it's okay to just set the class name and you can just set the class name and that's the simplest way to do it. It's probably the fastest way to do it as well. But it's something that you need to think about as you start talking about well, how can I get you know how can I reduce the amount of jQuery that I use. Think hard about that especially, I don't know, are Android 2.3 phones being sold widely here in India still? They are. Okay. So, you know, if you want to support those phones, you need to make sure that whatever solution you come up with still supports those browsers that don't yet include class list support. So I've gone over a few cases here where modern jQuery has changed the way it's worked, but it can be safe and effective when used as directed. Don't assume when you go out on the internet and start looking for solutions to your jQuery problems that the answers that you find, especially ones that are more than a year or two old, don't assume those answers are correct because even if they still work, especially if they still work but only if you include jQuery Migrate, don't assume that those are the best solutions still. Unfortunately, people just don't go back and update their eight-year-old blog posts. I don't know what. Instead, use tools like jQuery Migrate if, you know, if you're having problems or especially if you're trying to upgrade an existing site with an old version of jQuery. That will help you find those bad practices and fix them. And please don't just use jQuery Migrate as a way to prop your problematic code up forever. Migrate does a really good job of giving you error messages and we want people to continue to upgrade jQuery because each one of the versions that we put out improves performance. So every time you put in jQuery Migrate with an old version or even with the latest version, you're kind of destroying the work we've done. You're making jQuery slow again, which will probably affect your perception of whether jQuery is a good platform for you or not. So, you know, as much as you can, keep using the latest and greatest, we'll try to keep making it greater as we go on. So, I think we've got a little bit of time left if you want to ask some questions. I know there's some questions out there. Everybody comes up to me in the hallway and asks me questions. Here's your opportunity to have your question answered so that everyone can benefit. Yeah. Yeah, .live. It said, the question was, I mentioned .live and you wanted a little more elaboration on what I meant by that. .live has, well, actually if you go look at the manual entry, the jQuery documentation API entry for live, there's a big list of problems that live has. Just off the top of my head, some events don't bubble. They can't be used with live. Apple touch events don't bubble to document, so they can't be used with live. The selectors, the bubbling process is very expensive because if you're 10 levels deep, then we have to test the selector you gave against each one of those 10 elements on its way to the document to see if any of them meet the criteria. The list goes on and on, though. So, there are performance issues or reliability issues and that's really why we got rid of .live. You're seeing less and less code that uses .live. Usually, it's, again, old Stack Overflow answers, old plug-ins, and hopefully we can, over time, get rid of more of those and not have to be dealing with, you know, with you trying to figure out, is it safe to use this plug-in? Oh, no, it uses .live. Another question? Somebody had their hand up here. If you stretch, I'm going to assume you're asking a question. Yes. So, you mentioned that dollar.ajax setup is not a good practice to use. So, why do we still have that supported in our API? Why is Ajax setup still in there? Mainly because a lot of code still depends on it. So, it's kind of the same reason why it took so long to get rid of some of the other bad things. People will say, I have no better way to do this or, you know, as, I mean, if we could put out a version of jQuery that represented everything we wanted to do, it would be wonderful. The problem would be, I think no one would end up using it. You know, so Ajax setup is a good example where I would strongly advise nobody uses it, but we have the problem of trying, and also I want to make people aware of it so that when they write plug-ins, that they know they have to defensively program against it. But trying to remove it is much more difficult just because so many people currently depend on it to make their code work. So, we would be requiring that they actually go and, you know, rewrite a lot of their code. Hi, David. Yeah. Oh, okay. We are using extensively .on events, .on functions for the events. So, are there any best practices to use .on events to make our performance faster? I'm sorry, I didn't quite understand the question. So, there are two ways to bind the events. First, directly, you can bind events, .click, and all the things, and you can use dynamically using on. So, is there any bottleneck? Well, the form where you use a selector with it is somewhat similar to live, right? It just uses event delegation. Is that what you mean? Event delegation versus directly binding to a particular element? So, when you bind, event delegation is a really powerful technique. I think that, in particular now that everybody is in the MVC, that one good reason for avoiding live is that you probably want to make the container for your event delegation be the container for your view, and you don't want it to go outside that view. So, I think it's a fine thing to do if you want to make it, for example, so that all of the events in a view are bound to the view container, and then everything inside is just delegated to the container. Or you can bind them directly to the elements. Obviously, if you're, for example, you've got a table with 100 elements in it, it's much, much better to put the element on the table element or on the table body than to put it on each individual, you know, each individual row of the table. Yeah, one more question. Are there any best practice regarding even namespaces? We use even namespaces a lot in our application. So, are there any CVS or fall, I mean, drawbacks with it? Well, even asking about event namespaces means that you are a pretty good event, a best practice person already, because unfortunately, a lot of people don't use event namespaces. Especially in a large page, you can end up removing someone else's events. So, best practices on event namespaces, the main thing is just to choose names that are somewhat unique and to use them in your own code whenever possible. I think especially when you're talking about a plug-in, make sure that your plugins are using namespaces so that, again, it's a defensive maneuver to make sure that your plugins don't have their events removed by some other piece of code. So, I mean, you could use a small number of, you know, custom things like underscores if you want them to be really unique. I think the main thing is just to make them long enough and named probably like if it's a plug-in, put a prefix of the name of the plug-in. Hi, Dave. Over here. So, I wanted to ask you whether jQuery is going to support mobile events in the future like touch, drag, touch start. So, normally we have to use other plugins to rely on it or fast click. Well, fast click is a problem that was created by Safari, right? The ideal for us is that people would go to pointer events and then you wouldn't really have to worry about some of that kind of thing happening. Some of the other things about gestures, they're more high level. So, it's probably better to have them occur in a plug-in. The plug-in can generate an event you could listen to with jQuery. But if it requires measuring things, for example, knowing how far a swipe is or those kinds of things, it's probably better to put that out in a library because a lot of times you'll want to tweak that and maybe platform-specific. Ideally, in jQuery Core, we would like the events and things we handle to be a pretty cross-browser and do anything that's higher level elsewhere. So, when it comes to jQuery UI or the tep pointer event plug-in, we can put pieces together to build a full application. But we don't want to think that it has to all be inside jQuery Core to make it work. You pointed out certain things that are considered as bad practices in jQuery your ways you can shoot yourself. And when you look at the documentation, it's fairly nicely called out that this is not a good practice. It has performance issues and things like that. But one of the challenges where if you people go and read documentation, they typically, you know, try and use something. And if it works, they just use it. They don't kind of really think about the performance issue with it. So have you guys considered kind of putting a log debug message when someone uses something that's considered bad with the same warning that you have there? So if someone happens to use, they could see the warning as a debug message but not hurt performance in production. jQuery Migrate does some of that. The challenge there is that it adds a lot to the size of the file. And again, people can know nothing about jQuery or jQuery performance, but they can look at the size of the file. And we always get dinged for that. So I actually talked with Paul Irish on the Chrome team. And he, when he was debugging some of the performance issues he was looking at, we were trying to figure out ways that we could have Chrome tools actually try to identify some of these problems and propose solutions and say, you know, don't do this. That's also why we want to be able, for example, if we solve the problem in jQuery 3.0 of forcing layouts on show and hide, then when we saw it being used, we could say, oh, if you upgrade to jQuery 3.0, this problem will be solved for you. Right now we can't do that. So yeah, it's always difficult because sometimes, I guess we could detect the problem universally and then just have a little cryptic message and say, you're doing it wrong. Go see the documentation. But if we had a specific enough message, people always want messages that are very specific. And I understand why. So they'll say, why is it that I can pass on a data type that's not a valid name? It's like, well, because it could be a valid name, you know. And what they want is a message that says, warning, you have passed in something that isn't a valid name. And if we did that, we would have hundreds of error messages in the code and the code would be a lot bigger. Hi, Dave. Why do we have $.get in the API? We already have $.ajx where we can set the type to get. We do have get. We have get, post. Yeah, like why do we have a separate API? Oh, wow. Yeah, that is a good question. There was a point in JQuery's evolution where I think people were thinking along the lines of, what are the fewest number of characters that we can implement anything with? I am not a fan of get, post. You know, a lot of these that are kind of shorthand methods for a shorthand method because it does make it, I mean, they're implemented exactly that way. And $.get is just a little wrap around Ajax. Yeah, I mean, it doesn't even have the error thing. If suppose it does not go to success, it does not have an error block as well. Yeah, I completely agree with you there that a lot of those are not essential for the boiled down API. All you really need is Ajax. You don't need load, get, post because they can be built pretty simply off of the existing Ajax API. It's usually, those come down to, now that we've put them in years ago, trying to figure out whose code we break in the process of trying to remove it. And if you actually look at the implementation, it's that much. So there's almost more work in removing them than in leaving them in. Certainly today, as we look at what features we decide to add, we look really hard at those things because, yes, it's only this much code, but then it's several more pages of documentation and unit tests and team time and all of these other things that are involved that sometimes don't, when people talk about it's only this much code, when adding a new feature, they don't realize what the back end costs are. So you have a good point there and really if we had that time machine that we all would like, we probably wouldn't have it. Hi Dave. A few minutes ago you said that applying class at a body tag level is not a good practice. Is that only because it is at a higher level and it causes the whole page to get repainted? I'm sorry, which is not a good practice? Applying classes at a body tag level. Applying classes, if you don't need to apply a class to the body to change something about the layout of the body, it is better not to do that because it's not always but sometimes possible that the browser will think that the body class changing will mean that a layout needs to be done on the entire document. So a practice that I've seen done quite a bit in the past is someone applies a class to the body as a programming flag. I am done with doing this. I am in the process of showing a dialogue or whatever but it doesn't actually change anything about the display of the page. It's simply a flag that they use of has class later to see if the class is on the body that tells them the dialogue's being displayed. Instead of using classes for that, it's much better to either use JavaScript variables or data attributes because those will definitely not force a layout. True, I got the point, but my point is is it only because it is a higher level or is it okay to add such attributes, add class attributes at a lower level, such as a span or a small, at a lower level, devs, et cetera. But that also cause problems. It can cause problems. Anytime you add a class and if it potentially affects the presentation of the page and then only a few levels lines down somewhere in the same turn of the event thread, you go and try to access something having to do with the part of the page you changed. The browser will need to stop working on your code and go recalculate everything and give you the answer. So you want to try to avoid that case which is called force layout. Thanks, David. Hi. Sure. Yes. So what I understand from one of the previous sessions is that we could use Sizzle, the selector engine of jQuery, independently of jQuery. So could you give me some examples of projects for which Sizzle would be the right fit but jQuery would be an overkill? Probably the most common situation would be where if you decided in a project that you're not using jQuery but you want full selector support on really old browsers. I don't see that as being a really common need though because usually those places where you're not using jQuery you might be using like Angular or something. They already exclude those browsers to begin with. So they're probably today on that many places where you would need to do that. If you decided you were going to extend the selector syntax yourself, Sizzle provides a way to do that. And so if you were doing something a little out of the ordinary and you wanted to make your own custom selectors but again, not use jQuery, you could do that for Sizzle. Thank you. Are we good on time here? I think we're, okay, sure. So when you're doing large HTML manipulation, so it's not like one level deep probably, I've got a div and maybe a paragraphs or another spans inside it. So say two, three level deep hierarchy. Then obviously the, and if you have a dynamic data in that then manipulating that as a text or a string is messy. So instead of that, the jQuery plan to have a kind of, I mean, very lightweight version of templates just like how underscore does, is it on the plan? Yeah, I don't think we need them because there's so many ways to do templating now. You can use mustache, you can use, you can use, depending on what kind of templating you want to do, you can use ES6 translation with ES6 templates, you can use, if you're expecting to go to like DOM templates, you can use that syntax. So there's so many ways to do templates that I don't think we would want to create a competing one. Especially if it wouldn't make sense to try to do that in core itself if it increased the size of the core library. Cause I think the majority of people would use one of the existing solutions out there rather than ours. Okay, great, thank you very much. All right, did you guys enjoy the keynote? That shows by the number of questions, right? Typically that's how we measure how good the talk was. So thank you, Dave, that was very good. I at least learned a few things that I was doing in jQuery that was wrong. So that's always good.