What do you want to learn?
Skip to main content
by Elijah Manor
Do you need jQuery? Let's look at some common jQuery code snippets and rewrite them with native browser APIs or micro-libraries.
Start CourseBookmarkAdd to Channel
Table of contents
When to Use jQuery?
When Should I Use jQuery?
Custom Builds of jQuery
One other thing to consider is possibly using another library instead of jQuery. Maybe you don't want to go without jQuery completely, but you just want something with a similar API, but very much lighter. Well thankfully there are some options for you here. And on a side note, if you're using a library like Angular.js, then you don't need jQuery either because they have an internal component called jqLite, which is a mini version of jQuery that just does the things that it needs. But enough about that, let's redirect to alternate libraries. So a while back, Thomas Fuchs came up with a library called Zepto.js. You may or may not have heard about it, but it's essentially a smaller version of jQuery with a similar API. There are features that aren't included, which is why it's smaller, but for the most part it contains the pieces that you'd want and need. When it comes to a mobile application, I've heard of many who use Zepto because of its lighter footprint. As a side note, Zepto was an option before jQuery released its module custom builds in version 1.8. The Backbone.js website mentions that they require a dependency on either jQuery or Zepto, which is pretty interesting. One thing to note is that Zepto doesn't support Internet Explorer 6, 7, 8, 9 or 10 because it modifies __proto__, pronounced dunder proto for short. But interestingly enough, IE11 does support dunder proto, so you should be able to use it then. Another even smaller library written by Remy Sharp is called Min.js. It's a very minimalistic library that somewhat mimics the jQuery API. As you'll see in the upcoming modules, some of the syntax that I'll show you is more verbose than in jQuery version. So using a library like min.js can help reduce a lot of typing and make your code more terse. Additionally I wanted to mention an Experiment Dolla project that Burke Holland and Leland Richardson put together. It's a small recreation of the jQuery API that they put together as they wrote an article on TekPro. It's a good learning resource and shows some of the things that they had to think about and consider along the way.
Before we mention about certain features and certain browsers and how we made a decision of using IE9 and above, well how did we determine that? A good tool to use is caniuse.com. We could come in here into the search box and type classList for example, and we could easily tell that classList is not supported in IE8 and 9, but it is 10, 11, and pretty much most other browsers and versions. This helps us to determine that we probably need a polyfill for IE9 to support this if we want to use classList. Another example might be localStorage, and thankfully it's supported pretty much everywhere, which is really great, even in IE8. We could also look at something like querySelectorAll and we can notice it has really good support. However, if we look down in the notes, it'll give us some more interesting information such as the IE8 implementation is limited to the CSS 2.1 specification. Another nice one is the matches, which we'll talk about later. It's not actually supported fully anywhere, but it's partially supported lots of places using the old name of matchesSelector instead of the new name matches. It's also vendor prefixed with the old name, such as msMatchesSelector, webkitMatchesSelector, et cetera. So this is a really good tool just to kind of figure out where everything's at, and if we need certain polyfills to fill in the gaps. Next thing we want to look at is Zepto.js. We mentioned this is this really small library that is jQuery-like in its API. You'll notice on the left a lot of these look very familiar. If we come over to addClass for example, well that's in jQuery, you just say addClass and provide a string. Or you could provide a function that will determine what the class will be. And then we'll come over to Remy Sharp's Min.js, which is a very small library, but it feels very much like jQuery. You can select things of the DOM using the dollar sign, you could add event handlers with the on method, and you can loop over things with the forEach method. If we come in and look at the distribution, it's really small, it's only 69 lines of code. And again, so it doesn't provide a lot for you, but it helps make your code a lot more terse, and so if you want to simplify things a little bit, you could use Min.js. So here we're going to build a custom version of jQuery. First, you need Node installed and Git, but once you have those installed, you could just say git clone git://github.jquery/jquery.git. And that'll go and clone jQuery from the repository up in GitHub, pull it down to your box, it doesn't take too long, and now we have it. So then we need to make sure that we have the grunt command line interface installed and bower. So we could say npm install --g, for globally, and we want the grunt-cli, and we want bower. And that'll go out to npm, download those packages and everything they depend on, which is quite a bit. It'll take a just a second, but once those are down then we'll test to see if they're loaded correctly by saying grunt --version && bower --version. And sure enough, they both came back with a version number. So now we're going to go inside of jQuery and we're going to npm install, which will look into that particular repository and figure out all the packages that it needs, and it will install them. And so here it's going out and it's getting everything it needs. So now we're good. And then we could just say grunt, which will actually make the very first build of jQuery with all the components listed, all the modules listed, it'll go and build them and uglify them and make them into a nice little bundle, so now it has combined all the modules, made a jQuery.js and a jQuery.min.js. If we look at the folders, it actually created a dist folder, and we look in here and we can see that it created the jQuery.js, jQuery.min.js, and a jQuery.min.map, which has a source map file to help you actually debug through the minified code if you want, and Chrome has that feature right now. So that's pretty cool. So what we can do now is we can make a custom version of jQuery, and let's say we just want to take out the AJAX module and maybe the CSS module. So it'll take those two modules out, build the rest, and then give you a new version. So we could go back into our dist and here are our new files and they're a little bit smaller than they were before, so that's good, but really we're working off the master branches, which is probably not what we want to do. So, what we could do is we could say git checkout tags, and each version is tagged with a particular number, which is the version that has been released. So let's check out the 2.0.3 version of jQuery, and now it's saying that we're now at that release, and then we'll say npm install, because different versions might actually have different dependencies. So we're just going to say npm install just in case it needs things that we didn't have earlier. And once that's done, we'll do a normal grunt build just to kind of kick everything off to make sure everything is set up. And then once that's done, then we'll actually run our custom command. Alright, there we go. And now we can actually make our custom grunt build. And here say we don't want AJAX and we don't want CSS. And again we'll go out and just pull those modules, make a new version, and put it in our dist folder. And now that version will be the 2.0.3 version without the AJAX and CSS modules, whereas before we had just done it off the master, which is like the latest and it's not actually fully baked and not ready for production yet, but this version with the tag should be ready to go. And if the command line isn't for you, then there's a nice unofficial jQuery Builder website that we could use. Here we'll actually grab the 2.0.3 version like we did before, and we'll remove AJAX and CSS and you can actually see the file size getting smaller of what the end result will be. We could actually choose to have a minified version or not, and then we could say build, or we could actually pull this from our command line or actually install another module, but we're just going to click the button. And here it actually gives us this file, so we could just then save. And so here we could save this version as jquery-ajax-min, showing that we removed those modules and it's minified, and we could save it somewhere and start using it in our application, or we could rename it or whatever we want to do. But this is a much nicer alternative to having to work with the command line and installing all these things and not being familiar with that process.
So, as a summary, does your website cut the mustard? If you recall, that essentially means are you using Internet Explorer 9 and above and other modern browsers? If the answer is yes, then you may be able to do without jQuery. However, if the answer is no, then using jQuery is probably a good idea since there are a slew of features that aren't supported in IE8 compared to other modern browsers. If you still do end up using jQuery, which is totally okay, then maybe you could consider making a custom build of the library to only include the modules that you need or use. You do this either from the command line, or there's an unofficial website where you can do this. And if that's not small enough, then you could consider using Zepto.js, which mimics the jQuery API, but it's much more streamlined. However, it doesn't support Internet Explorer at all. Or, you could possibly use a barebones utility library called Min.js, which provides some helper convenience methods if you decide to use native browser APIs.
Hello, this is Elijah Manor. In this module, we'll focus on how to natively grab elements from the DOM and navigate around. This module, and others to come, will first show a snippet of jQuery code, and then we'll look at one or more additional snippets that will perform the same action, but without using jQuery. As I touched on in the last slide, the whole idea of selectors is to eventually find something you're looking for in the DOM. Typically we want to pinpoint either one element or a group of elements so that we could perform some action on them.
So let's first focus on various ways you would select elements using the jQuery library. You could select by ID using the pound syntax, you could select by tag name or by class name, and you could also send in a complex CSS selector, which really all the other examples are doing as well. Now when we move to not using jQuery, or jQuery-free, we have several options we could choose from. We could use the getElementById method off the document. This method turns out to be super quick in comparison to all the other examples we'll see. You could also use the getElementsByTagName, which will only get elements that match the tag name you provide. There's also the getElementsByClassName method, which actually only came out in IE9. So you should be fine as long as you're not supporting IE8 or below. And the most powerful option is querySelectorAll, which works very similar to jQuery in that it uses a CSS selector to identify a set of DOM elements. There's also querySelector, which is just like querySelectorAll, but it only returns the first element that it matches. I typically use getElementById, querySelectorAll, and querySelector.
Once you've selected the elements from the DOM, a common thing to do is to iterate over them. JQuery has a very familiar each method that you can invoke off the jQuery object after your selection has been made. If you didn't want to use jQuery, you could instead use the querySelectorAll method and then kick off a native for loop, incrementing an index and using that to access each item with a bracket notation. As it turns out, there are several other ways to do this that are much cleaner, so let's take a look at those as well. Another option to natively iterate over DOM elements is to use the forEach array method in ECMAScript 5. However, querySelectorAll doesn't return an array, what it does return is a node list, which unfortunately does not have forEach as one of its methods. What we can do though is access the array slice method and pass in the node list to convert it to a real array. Once you have the array, you could forEach over it and access it that way, which is pretty nice. However, that might seem like a little bit of extra work to iterate over the node list. Another way that I prefer better is to create a new array and call its forEach method, invoking the call method and pass node list as its context. This ends up being a little bit cleaner, and also gets the job done. Don't worry, we're not done yet, there's yet another way. So even that last example seems like a lot of work. What you can do is create a helper function to make things a little bit cleaner. In this case, we have a helper method named $$, and it accepts a selector and internally does all the weird code of calling slice, passing the node list, et cetera, and returns the converted array from the function. The end result is something that feels very similar to jQuery, but is still pretty close to the medal. If you do go jQuery-free, then you might want to consider making helper functions like this, or use the Min.js library or one of the others I mentioned near the end of module 1.
Another thing that sometimes happens is that you've already retrieved a group of elements from the DOM, but you're only interested in one of the elements in the middle. You're probably already aware of how to do this in jQuery, you could either use the eq method, the get method or the bracket notation and pass the index. Here we're getting the element at index 3. It's good to note that the eq method gets the jQuery wrapped element, whereas the get and bracket notation get the raw, unwrapped DOM element. The jQuery-free techniques are very similar in nature. If you were to use querySelectorAll for example, you could use the item method or the bracket notation like above and grab the element at index 3.
First and Last
Now that we know how to find the index, a common helper method in jQuery is getting the first and last element from the internal jQuery collection. In jQuery, you could call the first method, or you could pass the zeroth index to the eq method to change jQuery's internal collection to only include the first element. Or as we saw in the last slide, we could even use the get method or bracket notation and get the first raw DOM element. To get the last item, you can call the last method, or you could pass -1 to the eq method to change jQuery's internal collection to only include the last element. Or you could pass -1 to the get method or figure out the last index and pass that to the bracket notation to get the last raw DOM element. In a similar fashion, if you didn't use jQuery, you could still use the bracket notation that you get at the first element, or just use the querySelector method, which only gets the first match anyway. If you wanted the last item, then you could pass the last index to the bracket notation, or you could call the pop method off an empty array and pass your node list to the call's method's context. Either way, you will get the last item.
Once you have an element, sometimes it's handy to know what type of element it is. There's a handy method in jQuery called is that lets you pass a selector and test if it matches against the current element. The result is either true or false. As it turns out, it's pretty easy to do natively as well, all you do is call the matches method off the element and pass a selector just as you would with jQuery's is method. However, there is a problem. No browser currently supports the matches method, but many of them, including IE9 and above, support the vendor prefixed MatchesSelector method. So, I'm using a polyfill to provide the official matches method, which then in turn maps to the correct vendor prefixed method. This polyfill can be found at manor.im/jquery-free-repo.
Again, once you have a group of DOM elements, the next step might be filter them to a smaller subset. In jQuery you could use the filter method and pass another selector, which will reduce the internal collection to whatever matches that selector. You could also pass a function to the filter method. JQuery will loop over each item in its internal collection and invoke your callback. If you return something truthy, then that element will remain in the internal collection, but if falsy, that item will be rejected. If you took a jQuery-free approach to this, you could convert the node list to an array and just use the ECMAScript 5 filter method. To mimic the first overload of the jQuery filter method, you could use the matches method off the element to match the selector. And again, I'm using the polyfill I mentioned previously. In the second example where we pass a function, it's very similar to the jQuery version. If we return something truthy inside, then we want to keep the item, and if we want to reject it, we just return something falsy. The filter method returns a new array, which is a little different from what jQuery was doing before. JQuery was using the filter method to modify what was inside of its internal collection.
Sometimes you also need to search for elements from within those that you've already matched. To do this, you would commonly use the find method off the jQuery object and pass the selector that you want to find. For this example, we're finding the main element and then we're searching for input elements with the date class underneath that element. If you've already grabbed several items from the DOM, then you would also call the find method in jQuery and it would iterate over those items and search under each one to build up a new internal collection. Here we found all the divs on the page, and then we looked for all input elements with the date class underneath those divs. To do the equivalent thing natively, you could just call querySelectorAll off the element you've previously matched. Here, we've grabbed the main element and then passed the input date selector to querySelectorAll. That will give us a node list containing all the input elements with the date class. Things get a little bit more tricky if you want to find elements from a node list. The above jQuery example looks just as easy, but jQuery is doing quite a bit under the covers for you. To do this natively, we could write some code like the following. Here, I'm grabbing all the divs with querySelectorAll, and then I'm looping over them, and for each div, I call querySelectorAll again, and then I can concat those matched elements onto an inputs array that will contain our final result. Yes, that's quite a bit of code, but it does get the job done. Hopefully you're starting to appreciate what jQuery provides you, and this might encourage you to possibly use a small helper library for things like this, but it's not necessary, it's up to you.
Next and Previous
Sometimes the element that you have is close to where you need to be, but not exactly. In jQuery, it's really easy to move to the next or previous sibling node using the prev and next methods. Likewise, natively you could use the previousElementSibling or nextElementSibling property off the element in question. Thankfully this is pretty straightforward and the code is pretty simple.
Navigating to siblings is good, but sometimes you need to navigate up the DOM looking for a specific ancestor element. There is a parent method in jQuery, but I tend to use the closest method instead since it's less brittle. The way you call closest is to pass a selector and jQuery will first check the current element to see if it's a match, and if not, it will navigate up the DOM tree testing each element until it finds a match, and then it returns that element in the jQuery collection. Unfortunately, there is no closest method that we'd use natively, but here is the through process behind it. We find the element where we want to start, and then we start a loop and test each element to see if it matches our selector. If it doesn't match, then we'll grab the parent node and try again until we find a match. This is a little cumbersome, but as we'll see in the next slide, there's an easier way. So writing all that code each time would be cumbersome, and it was a little naive, so here's a little script to add this functionality to the element's prototype so that it's handy whenever you might need it. Once included, you could use it pretty simply as seen here at the bottom. We're using getElementById and then we're calling closest, passing the selector to match. In case you'd like to look at it further or use it in your project, the script can be found at manor.im/jquery-free-repo.
So, as a summary, with jQuery you could select an element or elements by using a CSS selector using the jQuery function. Likewise in jQuery-free land, you could also use the querySelectorAll method that's off the document object. This method also takes a CSS selector and is available in modern browsers. Once you have a list of elements selected from the DOM, you could use jQuery's each method to iterate over them, or you could use the native array for each method to iterate over the node list returned from querySelectorAll. However if you recall, there's no forEach method off a node list, which is why we're using the array's forEach and passing our list as its context. When you have a list of items in the jQuery internal collection, sometimes you want to access just one of them. To do that in jQuery, you could use the eq method and pass the index of the item that you want. To do this with a node list, you could use the square bracket operator and reference the index of the item that you want as well. If you want to test if the item you've selected matches a specific CSS selector, you could use the is method in jQuery, or if you have the raw DOM element you could use the matches method that we've polyfilled. If for some reason you've selected too many elements, then you could use jQuery's filter method to reduce the list to a smaller subset of items, in this case based on a CSS selector. If we wanted to do that with an array of elements, then we could use the native array filter method and return the result of the matches polyfill method. However, let's say that we have one element and that we want to search for items underneath it. In jQuery, you could use the find method to do that. Without jQuery, you could call the querySelectorAll method off a raw DOM element to do the same thing. The end result is a node list. If you wanted the next sibling of the element with jQuery, you could call the next method, whereas you could access the nextElementSibling property off a raw DOM element to do the same thing. Lastly, if you wanted to navigate up the DOM looking for an element that matches a selector, then you could use the closest method in jQuery. Likewise, you could also use the closest helper method that I showed earlier in this module to do the same thing. So, that's it for this module.
Native DOM Manipulation
Hello, this is Elijah Manor, and this module covers DOM manipulation. We'll show how to manipulate the DOM with jQuery and then how you could do the same thing with native browser APIs. DOM manipulation is a common task in most any web application. We're either creating elements or modifying them all the time. Maybe we're adding a class or changing a style or adding new content. These are things that are necessary for a very interactive web app.
For example, manipulating classes on an element is a very common task. With jQuery it's very easy. JQuery provides addClass, removeClass, toggleClass, and hasClass methods to help you manage this. Adding is pretty straight forward, and it allows you to add several classes at a time. ToggleClass is pretty handy and smart. If the class is present, then it'll be removed, but if it isn't there, then it will be added. And hasClass is a nice way to let us know if the class is already applied to the elements or not. Things are a little more complicated if you decide to not use jQuery. In IE9 and older you would need to somehow manipulate the className property off the element. It would be up to you to concatenate to the property or somehow manipulate it with a regular expression or a fancy index of string manipulation, which is probably something you don't want to be doing by hand. Thankfully, there is a classList standard that's implemented in most other browsers and IE10 and above. ClassList looks very familiar to the API that jQuery has. There's add, remove, toggle, and contain methods. Thankfully, you could polyfill for classList if it doesn't exist in your browser, which is what I recommend for IE9. You could grab it at https://github.com/eligrey/classList.js. As you can see, the browser support is pretty good, except for IE9, which is why I recommend using the polyfill.
HTML and Text
A common thing that you'll need to do is to replace the text or HTML of an element. You could do this with jQuery using its HTML and text methods. If you call the methods without an argument, then they're a getter, and if you provide a string as an argument, then they're a setter. Going to jQuery-free isn't too hard at all in this case. All you have to do is access the innerHTML and innerText properties off the element, and then you could either read them as a getter or assign to them as a setter, and that's all.
Append and Prepend
It turns out that appending and prepending with jQuery is pretty easy. There are prepend and append methods where you pass some HTML markup and jQuery will create the elements for you and insert them into the DOM. When you move to native APIs, you have to do a little more work. You'll need to manually create the elements you want to insert in the DOM, manipulate their properties, in this case we're updating the inner text, and then you could call the insertBefore or appendChild methods. Coding for this could get somewhat cumbersome as your markup gets more complex. For example, if we wanted to create a table, we'd need to build up each element, table, TRs, TDs, et cetera, and assign their relationships to each other manually before finally inserting the table into the DOM.
Sometimes instead of hiding something from the DOM, we want to actually remove it completely. In jQuery this is pretty easy and there are several ways we could do it. You could call the empty method, which will wipe out the innerHTML of that element, you can explicitly set the innerHTML to an empty string by calling the HTML method or you could call the remove method off the jQuery object. Without jQuery, you could do some of the same types of things. You could set the innerHTML to an empty string, you could create a loop and continually call removeChild, deleting the last child property until they're gone or you could grab the element's parent and call removeChild on the element.
Attributes and Properties
Now let's talk about accessing and changing attributes and properties for a minute. Historically, jQuery only had one method to do this, the attr method. But as of jQuery 1.6, it introduced the prop method as well. The main distinction is that the attr method is meant for attributes, and the prop method is meant for properties off the DOM element. Properties are dynamic and don't update the corresponding attribute when changed. For example, the placeholder is an attribute that you could read and write to, but let's consider the checked property on an input field. Once the user checks the input box, if you asked attr the value of checked, it wouldn't reflect that it's been checked by the user, you'd need to use the prop method instead to test for that. Another interesting distinction is if you check the href with the attr method it will give you the relative path, or whatever you provided as the href in your markup. But if you used the prop method instead, it will give you the fully resolved path, which you may or may not want depending on your circumstance. When we look at the native version of getting and setting attributes and properties, the jQuery code starts to make a little more sense. Here we have setAttribute and getAttribute methods, and also corresponding properties of the element that we could check and assign. Likewise, we get the same behavior when we access href, either by getAttribute or the href property. Since these concepts map over pretty well, there isn't much of a learning curve, which is nice.
If you're dealing with form elements at all, you'll typically need to read or set the values of those fields. With jQuery, there's a val method. If you don't pass an argument, it'll get the value and if you pass an argument to the method, it will set the value. Likewise, if you don't use jQuery, there's a value property that you could either read or set by assigning something to it, and that's all.
Height and Width
Manipulating height and width is actually considerably complex inside of jQuery. If you open up the source code, you'll see that it's doing a lot of things to make it work correctly. If you look at the image on the right, you'll see that there are a lot of factors to consider, like margin, border, padding, and the original dimensions. JQuery has some methods to assist you here, like width, innerWidth, and outerWidth. When you move to the non-jQuery land, there are properties you could use as well, such as clientWidth, offsetWidth, and you could call the getBoundingClientRect method and get its width. If these techniques get you the value you need and it works for your application, then great. However, you might have to provide some extra logic depending on how your element is positioned or styled. Just keep that in mind. Just for kicks, let me show you how non-trivial the jQuery source code is. I don't expect you to understand all of this, but just be informed of how many edge cases there are, and we're not actually seeing all the code here. There are other methods that are called from within here too. The main takeaway is that you could try clientWidth, offsetWidth, and the like, but if they don't work right away you might have to dig a little bit deeper.
So, as a summary, in jQuery once you've selected an element, it's really easy to add a class using the addClass method. Likewise, if you had a DOM element, you could use the classList API and call the add method. This is only supported in IE10 and above, so you'll want to use a polyfill. A common thing that you'll need to do is to update the HTML of a particular element. In jQuery, you could use the HTML method and pass a markup, whereas if you're using a native DOM API, you could use the innerHTML property. In addition to updating the current element, you could also insert new elements into the DOM. An easy way to do this with jQuery is to call the append method, passing new markup. Or, without jQuery you could create an element with document.createElement, manipulate it, and then call the appendChild method, passing in your new element. After adding a new item in the DOM, you might want to remove it. With jQuery, you could just call the remove method, and without jQuery, you could call the removeChild method off the parent to remove a certain element. If you want to change the style of an element in jQuery, you could use the CSS method, passing the style name and value. The native way to do this is to change the properties off the style object. In order to change a property of an element with jQuery, you could use the prop method and pass the name and value, kind of like you would with a CSS method. And the native version of this is just to access the property of the same name off the element object. It's a pretty common thing to have form elements on your website, and because of that, chances are you'll need to access the value of one of those fields. In jQuery, you could use the val method to access the value, and without jQuery, you could just access it using the value property. Finally, getting the width of an element is pretty common as well. There are several ways to do this jQuery, but one of them is the outerWidth method. Natively, you could use the offsetWidth property, but you might find that this doesn't give exactly what you need. You'll need to make sure that this gives you what you need, and if not try another technique instead.
Hello, this is Elijah Manor, and in this module, we'll be talking about events. We'll look at how to manage events in jQuery, and then we'll look at how we can provide the same behavior without using jQuery. Events are a crucial part of most web applications. At some point or another, you'll need to interact with the user somehow, either if it's to respond to a button click, their scroll position or keys they're typing.
Bind and Unbind
There are several ways in jQuery to add an event listener to an element. Here we can use the click event helper method and attach a callback, or we could use the bind method and pass the event type of click and provide a callback as well. Additionally, we could also use the on method, passing click and the callback much like we did with the bind method. That might seem like a lot of ways to do the same thing, but there's a little bit of history behind all those decisions, which we won't go into right here. Anyway, that's jQuery. The previous example showed code when we had selected just one element, the element with ID of save, but it's just as easy if we had selected several items from the DOM, like the following example. Here we're selecting all the buttons on the page and adding a callback when they're clicked. Behind the scenes, jQuery is looping over each element in its internal collection and adding the click event handler to each one. If we switch over the native way, we could use addEventListener and provide the event type and a callback to be invoked when the event occurs. So here we're grabbing the element with ID of save, and then adding a click event handler using the addEventListener method. Now that seems pretty straightforward, however, once you want to add event handlers to a group of items, the code isn't as elegant as the jQuery version. Here we have to loop manually, whereas jQuery did it behind the scenes for us. So, we're finding all the buttons on the page and looping over them and adding a click event handler to each of them. You might notice that we're attaching the same callback for each of the items instead of creating a new one. So if we want to unbind our event handler, we could use the jQuery off method. You could also use the unbind method as well, but it's just a one line statement to call the off method. There are several overloads you could use with the off method. If you don't provide any arguments, then it will remove all the event handlers for all event types. If you provide just an event type, then it will delete all event handlers of that type. And if you provide a namespace, then it will only delete event types that match your namespace. And you could also remove just one event handler if you have a reference to it. The above code samples work if we only have one element selected in our jQuery object, or if we have selected a collection of elements. In order to unbind a native event handler, there aren't as many options. JQuery really does provide a lot of functionality, but with native we pretty much only have removeEventListener and we need to provide both the event type and a reference to our callback. If you selected a group of elements, then you'd have to loop over them and call removeEventListener individually. Again, this is much easier in jQuery because it does that loop under the covers for you.
Delegate and Undelegate
There are actually other ways to add event handlers in jQuery other than the three ways I've already shown. You could also use the delegate method and the three parameter versions of the on method. The behavior of these two are the same in that they're attaching metadata at some point higher in the DOM, and react to a triggered event. If an event happened that matches their criteria stored, the selector and the type, then our event handler will be invoked. So the above examples are selecting the container element and storing some special information on it, a selector, an event type, and an event handler. If an item is clicked on underneath the container that matches the widget selector, then our callback function will get invoked. If we don't use jQuery, then we could call the addEventListener method, and inside the callback, we could check to see if the target of the event matches the selector that we're concerned about. And again, we're using the matches method, which is polyfilled for IE9. If the target is a match, then we'll execute whatever code we intended inside the if statement. Unfortunately, there's an issue with the last native solution that we just saw. If the item we clicked on is a child of the selector we're trying to find, then there won't be a match. So, we could do something like this instead where we try to match what was clicked on and then grab its parent to test it until we go all the way up to the element where the event handler was attached. So in this example, we add an event handler to the container, test the element that was clicked on, and climb up the DOM, testing each element along the way until a match is found, or we reach the container. If a match was found, then we could execute whatever code we want. Yes, this is quite a bit more code to do something that jQuery made very easy. We could clean this up somewhat by using a helper method. I've pulled this code out into a closest helper method and included it in the jQuery-free repo so that you could simplify your code to something that looks like this. Here we just call the closest method off the target and we optionally provide the implicit this parameter to let the method know when to stop looking at the DOM. If we didn't provide this second argument, then it would have navigated all the way up the DOM tree until it hit the document or until it found a match. When it comes to undelegated with jQuery, you have lots of the same options that we saw earlier. Here you could say off to all event handlers for everything, or you could be a little more specific and limit our destruction to only a particular selector in event type. We can get specific and also pass an event handler instance that we attached previously. Or we could say remove all namespaced event handlers as we did before. When it comes to undelegated native, it's the same as we saw before. We need to call removeEventListener on the parent node that we were using to watch the DOM. Since the matching logic was in the event handler itself, we don't have to worry about that.
Prevent Default and Stop Propagation
If you click on an anchor or submit a form, then sometimes you'll want to prevent the default behavior of the browser, either redirecting or posting to the server. The process is exactly the same in both jQuery event handlers and native event handlers. You call the preventDefault method off the event passed to the handler. You could also prevent the event from bubbling up the DOM tree by calling this stopPropagation method. This is also the same with both jQuery and native techniques. As a side note, in jQuery if you return false from an event handler, it's converted to mean both preventDefault and stopPropagation, which you may or may not have wanted. So I usually recommend not using return false and instead explicitly saying what you meant in code. It also helps other developers know what you really meant to do.
Target and Which
Another thing that's the same in modern browsers is the target and which property is off the event object. Whether you use jQuery or the native addEventListener, you'll get access to the target of the element, the element that was interacted with, and access to which, which is the key that was pressed if an event was keyboard related. Which is a newer property, it came about as a normalization between key code and char code when they were across browser differences. However, if you're using IE9 or above, then you don't have to worry about such concerns.
By default, the this implicit parameter in an event handler is the element that triggered the event. In this case, it was the search button that we clicked on. If we want the this context to be something else, then we could use the jQuery proxy method as shown below. Here we're telling jQuery that we want the this context to be the store object once we get inside the event handler, which enables us to read the category property when building the URL variable. Without using jQuery, the process is pretty similar, but we don't have the proxy method available to us, but that's not a problem because ECMAScript 5 has a bind method that behaves in a similar way. Here we tell addEventListener to use the store clickHandler method and to bind this context to the store object. And now this will work just the same as the last line.
Once you have all these event handlers in place, sometimes it's nice if you could programatically trigger them instead of rely on the user initiating the events. In jQuery, you could do this by calling the trigger method off the jQuery object, you provide the event type and optionally any data that you want to send along with the event. In this case, we're triggering the click event on the tab element, once with no data and a second time passing two additional arguments. You can do something very similar with native APIs, but it looks a little bit different. First you set up your event handler with addEventListener. If you want to create an event that has no additional parameters, then you just create a new instance of event with the type of event and then you call the dispatchEvent method passing your event. If you do want to pass along some data, then you create an instance of CustomEvent, tell of the type of event, and then provide your custom data. And then just like before, you pass your event to the dispatchEvent method. And as you can see here, the detail information that we sent along with our custom event is available off the event object on the detail property.
So, as a summary, it's pretty simple to wire up an event handler with jQuery, you just select the element that you want and then call the on method providing the event type and a callback method to be invoked when the event occurs. And thankfully, IE8 and above and other browsers allow a similar syntax using the addEventListener method off the document object. You also pass the event type and a callback method. jQuery also provides a three parameter version of the on method that delegates listening to an element higher up in the DOM tree. In this case, we're letting the main element listen for click events on any element that matches the button CSS selector. We could do something similar with native DOM APIs, but it requires a little bit more code. Here we're attaching an event handler to the parent element, main, and then we're testing the event's target, looking for its closest button. If that was found, then it matches what we want, so we'll handle our logic there. A nice feature that jQuery provides is the proxy method, which allows you to change the this implicit parameter inside the event handler when it's invoked. By default, it's the DOM element in question, but in some cases you'd like it to be something else. In this case, we could ask jQuery to let it be the store object. Without jQuery, it's actually not very difficult either. You could use the ECMAScript 5 bind method to get the same behavior. Here we're passing the store object to the bind method. And finally, once you've set up all these event handlers, it can be nice to programatically trigger one of these events. In jQuery, you could call the trigger method and provide the event type that you'd like to simulate. Without jQuery, you could new up an event object, passing the event type, and then call the dispatchEvent method off your element with the event. And that's that.
Hello, this is Elijah Manor, and in this module we're going to talk about making AJAX requests. JQuery does a really good job at making AJAX requests easy, so we're going to review what it looks like in jQuery, and then we'll look at how to make AJAX calls natively. AJAX has actually been around for quite a while. Internet Explorer introduced the technology back in 1999 with IE5. Since then, it's been adopted and modified by other browsers as well. In this module, we'll take a look at get and post requests, as well as JSONP.
In order to make a get request, jQuery has a nice get helper method. You pass in a URL for the request, optionally provide it data, and then a function to call back when the response arrives. Due to the same origin policy, the protocol, domain, and port of the URL need to be the same as the requester's location. Instead of calling jQuery's get helper method, you could instead call jQuery's low level AJAX method. The idea is the same, but the syntax is a little different, and there's a lot more options to control. You pass an object to the AJAX method and inside of it you could pass things like the URL, optional data, what type it is, a success callback, an error callback, and lots of other things. If you don't want to use jQuery, you could instead new up an instance of XMLHttpRequest and call the open method providing the get verb, a URL request, and an optional async flag. Then you provide an onload callback that'll be invoked when the response comes back from the server. And finally, you kick off the request by calling the send method. All in all, not too bad.
In a similar fashion, jQuery has a helper method to make a post request. You call it the same way as before, you provide a URL, optional data, and then a callback. And like before, we can call the low level jQuery AJAX method to make a post request. JQuery will make sure to send the data provided in the appropriate way, depending if it's a get type or post type. Without jQuery, you still need to create a new instance of the XMLHttpRequest and open it like we did before, but this time we tell it we want to POST. In addition, we set the request header to indicate that we're passing some form data. We setup our onload callback, and then when we kick off the request by calling send, we could pass along some additional data. A nicer way of sending along post data is using the formData object. You could build up the data you want to send by appending new keys and values, and then passing the formData as the parameter to the send method. An important note is that IE9 does not support formData, so if you want to use this technique, you'll need to use a polyfill. Another nice way of using form data is that you could pass it a form element from your page, and it will append all the appropriate keys and values for you. And then all you have to do is pass the formData object to the send method like we did before.
A common technique of requesting information from another server is to use JSONP, which allows you to get around the same origin policy. JQuery makes this type of request look as if it were a real AJAX request, but it's really not. All you have to do is provide a dataType of JSONP, and the rest looks like it's just any other get or post request. In the same way, if you used the getJSON helper method and provide a callback URL parameter, then jQuery will wire up all the special JSONP pieces for you and it'll just work. So what's really going on then? Well it's easier to see if you don't use jQuery. If we want to make a JSONP request, then what we have to do is create a new script element, set its source to some remote source, and insert it into the DOM, we set the callback URL parameter to a function we have on our page, and we wait for the server to respond. Now, an important note here is that the server will have to notice that we're sending a callback parameter and it will need to wrap its JSON data as a parameter to our JSONP callback function so that when the response comes back, it'll invoke our function and we could handle it appropriately. So, as you can see, jQuery is doing a lot of trickery for us, but it looks like it's just a plain old XMLHttpRequest, but it's very much not.
So all of this might be a little too much for your taste. Another alternative is to use a micro library to handle your AJAX requests. If you're going to use one, I recommend using the Request library if you'd rather not use the low level XMLHttpRequest. This tiny library is very rich and supports a lot of the nice features that jQuery has, but without all the other modules that you might not need.
Alright, here's our application again. And what we're going to do this time is we're going to swap out the jQuery AJAX call, actually it's using a JSONP request, and we're going to change it to use a native form of the JSONP request, which is kind of interesting. So let's come over here and look at the $.getJSON and this special callback=? is a special thing that jQuery recognizes and does all the JSONP magic. And of course the server that we're talking to, the Yahoo API, has to understand this as well, and they do. So what we're going to do is we're going to replace the question mark with a function of where we want it to go when it's done. So we're going to say blog.jsonCallback. And of course we don't have that defined yet, so let's say blog.jsonCallback. And we'll make a new function and we'll pass the data into that function. And so what the server will do is it'll see that we're expecting blog.jsonCallback to be invoked with some data, and so that server will get all the data that it needs, and then before it ships it over, it'll actually surround the data with blog.jsonCallback. So it's kind of invoking our method, but shoving its data inside as a parameter. So once it gets to our side, since we're going to create a script tag and imbed on the page, it'll actually invoke the response and we'll have this magic method waiting for us and it'll get invoked passing the data, which is really cool. So we'll keep all this same, this URL, and then the next thing we'll do is we'll have a script and we'll actually create a new element, createElement, and then we'll create a new script tag. And most all this, we'll take this out, we don't need that anymore, and we'll put this in our special function. And then up here what we're going to do is set the scripts source to the above URL. And the last thing we're going to do is grab the document.head and we're going to append a new child and we're going to append our custom script. And we can actually delete this, save it off. So once we've injected the script in the head, then it will actually go make the request to Yahoo server, then it will actually go and get the RSS feed, get all the data back, surround the data with blog.jsonCallback, and then it will come to the page and be evaluated, and then it will notice oh, well I need to invoke the jsonCallback method, and hey, it's right here, and I want to pass the data that they sent me. And then I could just do all the rest by itself. So I'm not actually going to refactor this piece of code yet, we'll reserve that for another module, but the rest of it should just work. So, let's come back to our browser and we'll refresh, and sure enough, we got all the data and we're using our custom JSONP request that we're wiring up manually, we're not actually using jQuery at all right here. And so that's all you have to do, it's kind of weird. Of course this is a JSONP request, if it was a real XMLHttpRequest, then it would look differently, but that's what we talked about in the slides.
So, as a summary, jQuery makes it really easy to make AJAX calls. For example, you can call the get method, pass a URL to the request, and a callback method to capture the response. To do this natively, it's actually not that difficult either. You new up an XMLHttpRequest object, open it with a get verb and a URL, provide an onload callback, and then send the request. Making a post with jQuery is actually just as easy as the get. Here we're calling the post method off the jQuery object, passing a URL, some data, and a callback method. In order to do this natively, it isn't as straightforward or as nice. We still need to do as much code as we did before, but now we need to set the request header and make sure to send the data formatted in a special way. I did show a cleaner way to do this with formData previously, but if you don't want to use a polyfill for that, and you'd like a simpler syntax without having to use jQuery, then I recommend using a micro library called Request. It enables you to have a much more terse and full-featured experience like you're used to with jQuery.
Hello, this is Elijah Manor, and this module is about utilities that are helpful when making web applications. We'll look at helpful jQuery utilities and then show how these are also available natively, and if they're not, we'll talk about using a micro library instead. Once you've retrieved data from the server, you need to do something with it. It's handy to have a set of utility methods to make manipulating data easier. In addition, you'll probably find yourself needing the same type of code over and over again, which is where utility methods can come in handy.
We'll start with jQuery's data method. If you add an HTML5 data attribute to an element, you could use jQuery's data method to retrieve the data, or you could use the attr method. With the attr method, you have to provide the full attribute name, such as data-contact-name, and a string value will always be returned. If you use the data method instead, you drop off the data, remove the dashes, and camelCase the key and jQuery will return a value of the appropriate type, a string, a number, array, an object, et cetera. So here when we ask for options we get the value in object form. Behind the scenes, jQuery converted the JSON string to an object for us. Another way to use the data method, which has actually been around before HTML5 data attributes, is to just get and set rich data onto the element. Here we're attaching an object under the data key of a person. If we wanted to get that object back out, then we just call data again, passing the key of person. Now when we go native, there isn't a rich way to get and set objects, but we could manually parse strings and objects if we need to. Here we're using the getAttribute and setAttribute methods off an element to manipulate HTML5 data attributes. You'll notice that we're using the full name of the attribute, data-contact-name. If we need to store something richer, we could use JSON.stringify to serialize an object to a string in order to save to the attribute, and then we could use JSON.parse when pulling out the JSON string to convert it back into an object. There is another way we could get and set HTML5 data attributes, and that's with the dataset object. Using this technique, you could use the short camelCase version of the data attribute to get or set its value. Here we're changing the HTML5 data attribute, data-user, by setting contact.dataset.user. You could only provide data set string values, so if you need a richer data type, then you could use JSON.stringify or .parse to convert a string to and from an object. Unfortunately, dataset is not available in IE9 or IE10, so you'll need to provide a polyfill if you want to use this feature. You could find one at manor.im/polyfill-dataset. Instead of using this feature, you can just use getAttribute and setAttribute if you want.
The next utility methods we'll look at are each, grep, and map. These are very common methods that I use quite often when developing a web application. We're going to use the following data here as we exercise these utility methods. Here we have an array of languages with an id, date, and by attributes. The each method is a way to iterate over an array. You pass the method in an array and a function that you want to be invoked for each item. In this example, we're just logging a message to the console. The grep method is a way to search or filter only for a subset of items in an array. You provide the original array, and then a function that you want evaluated for each item. If the function returns something truthy, then that means you want to keep that item, and if you return something falsy, then you want to reject that item from the resulting new array. The map method is a handy way to transform what each item in the array looks like. Here we're calling the map method, passing in the original array, and much like the other methods, a function that will be invoked for each item. Whatever you return from this function will represent what that item looks like in the new array. So this is a nice way to change property names, trim down a huge object, possibly manipulate values or add new ones. In this case, we only wanted two properties in our object, a name, which is the ID of the original object, and an age property, which is how old the language is. The end result is something that looks like this, an array of three items, only the ones that had the string script in their ID attribute. And each object only has two properties, name, which was the ID previously, and a new age property, which is how old the language is. If you don't use jQuery, then the transition is pretty easy because ECMAScript 5 has new array methods that map to each method. There's a forEach method for looping, a filter that will serve as our grep, and a map method, just like we had before. The way we pass the function and use it is just the same as the last slide, but overall it's a little bit cleaner because we don't have to pass in the array since we're calling the methods off of our array. And the end result is the same as before, we get an array of three objects with names and ages. There is another option you could have taken with this. Instead of using the ECMAScript 5 array methods, you could have instead used the underscore or low dash, each, filter, and map methods. Since we're using IE9 and above, I would go for using the native array methods, but if you needed to support IE8 or less, then underscore or low dash would be a better fit. You could have used an ECMAScript 5 polyfill, but since I tend to include underscore or low dash anyway for other reasons, I'd rather just use one of those instead of using a polyfill. And if you need top performance, you might actually get better results using low dash anyway. However, it's really up to you and what you feel comfortable with.
Sometimes you want to know if an item is in an array or not. JQuery has an inArray helper method that you could use. You pass the item you want it to look for as the first argument, and you pass the array to look in as the second argument. If the item is found, the method will return the index at which the position it was found. Otherwise, it will return -1 to indicate it was not found. If you want to convert that to a falsy/truthy value, then you could use the tilde bitwise operator trick, and in this case I'm also converting that to a Boolean using the double bang trick. A non-jQuery way to do this is to use the ECMAScript 5 index of method off the array and pass the item you want to look for. The return value is the same as jQuery's in array in that it's an index or -1, so I'm using the same tilde double bang technique. As a side note, there are lots of other methods in underscore and low dash dealing with arrays and collection manipulation. I highly recommend you looking into one of these libraries.
The last utility method we'll look at is trim. Whenever you take input from the user, you probably should consider trimming the results. Trim just takes off the beginning and end whitespace that usually isn't intended by the user. JQuery has its own trim method, and also modern browsers, including IE9, supports the trim method off the string. So that's a very easy alternative.
Hello, this is Elijah Manor, and in this module, we're going to talk about web animation. Browsers have come a long way when it comes to CSS. We're going to take a look at several animation techniques using jQuery, and then we're going to compare how to do the same thing with CSS only.
Before we proceed with examples, I wanted to mention that I'll only be showing standard CSS properties instead of adding all the vendor prefixes. There are many techniques you could use to add these prefixes later. You could add them by hand or use one of these tools listed here, like --prefix-free, Prefixr, Autoprefixer, Compass for Sass or Nib for Stylus. Whatever you do use, it is important to add them somehow, but just for clarity we're just going to remove them in the slides.
Sliding elements in jQuery is also very easy to do because there are slideUp, slideDown, and slideToggle methods. What we're going to do here is when the user clicks the button, we're going to grab the block with jQuery, and then call the slideToggle method, which will slide it up on the first click and slide it back down on the second. Here, we're using a CSS transition again to help us with the sliding animation. This time we're telling the transition that we want to animate based on the height over a .4 second duration in a linear fashion. When the user clicks the button, we toggle, add or remove the slide-block class, which divides a height of 0, kicking off the animation and making it slide away. When we click the button again a second time, it removes the class, which makes the height go back to its original value, which kicks off an animation and slides it back down. Here we have another example in JSFiddle. We have a block up here with jquery and css3, and we have a button that says slide. With our jQuery version we'll grab the button, we'll grab the jquery-block, and just say slideToggle, and that'll kick off whether it needs to slide it away or slide it back. And then with the native code, we're going to select the button addEventListener, and then we'll select the css3-block and then just toggle the slide-block class. And over here, our css3-block, we define a transition that we want to listen for the height. So if that changes, we want to kick off animation over .4 seconds in a linear fashion. And here we're adding a class of slide-block, which sets the height to 0, which kicks off our transition, since it's based on height, over a .4 second duration, and it'll slide away. And then when we remove slide-block, then the height goes back to the original value and it transitions back to the original value. So if we click the button here, we'll notice both of them slide away, and then they both slide back. Very nice.
You might have noticed that I've used linear and ease in some of the previous examples. Well these are examples of easing algorithms, which are basically mathematical expressions which explain the progression of an animation, like if they start off slow and then get fast near the end, or if they're fast and then slow down and they're fast again, and things like that. There are several easing algorithms built in, but then again you could create your own custom ones as well. The website easings.net lets you visually see what the algorithms look like and you can see how to support them both with jQuery and with CSS. In this example, we're going to animate the left position of our box from its current position to 300 pixels. The animation will take place over 600 milliseconds and will use the easeInOutQuad easing algorithm. JQuery UI comes with lots of these easing algorithms built in that we could take advantage of. From the easings.net website, the easeInOutQuad page will show you how to support this type of easing just using CSS. It shows using the cubic-bezier function with values .455, .03, .515, and .955. In addition, there's another website called http://cubic-bezier.com where you could drag around four different points and define your own custom animation timing. So, we could use the information from easings.net and use it in our CSS transition. Here, we tell our transition that we want to use the cubic-bezier of .455, .03, .515, and .955, which will be the equivalent to the easeInOutQuad like our previous jQuery animation example. We'll tell it to animate the left property and do it over 600 milliseconds, then when we add the move class, the animation will begin just like our previous example. Now we could have instead used animation key frames, but in our case it seemed like a little overkill since our 0% frame doesn't really have anything defined, but the same idea applies. The main thing to notice here is that we're providing the cubic-bezier function with the values from our previous slide, and we're adding the move class to kick off the animation. So here's another JSFiddle with our easing algorithm. We're using the jQuery version on top and when we say animate, we'll actually provide the easing algorithm at the end, easeInOutQuad, and then we have our css3- transition and animation. And the main thing to notice since we've already talked about how to do animation, is that we're providing the cubic-bezier function with the custom animation that mimics what easeInOutQuad would look like. So when we click on them, they go fast and they kind of slow down near the end, which is really kind of nice. And so these are hardware accelerated and on your machine using the GPU, and this is just the standard jQuery version, and if we run it, we'll actually see it's leaving a trail, which is not optimal, but it is using the special easeInOutQuad algorithm.
As I mentioned before, IE9 does not support transitions or animations, so most of what we showed here would not work. So what do we do then? Well, one option is to not use CSS animations at all, but that would be unfortunate. CSS animations are super-fast because they can be hardware accelerated by the GPU, whereas jQuery animations are done in jQuery and aren't as performant. Another frame of thought is if the browser doesn't support CSS animations, that we just let those browsers not get animation. That could be okay for your application or not. It really depends if those animations are crucial to the app or not. Another approach is to have a jQuery fallback if the browser doesn't have native CSS animations. This is a little bit trickier, but it's doable, or you could possibly use a plugin like jQuery Transit or jQuery-Animate-Enhanced. You could use something like jQuery Transit, which will use CSS animations, if they're supported, integrate gracefully for older browsers. You could also write a small snippet of code to conditionally check for transition support and then reassign transition to the jQuery animate method if you need to. Or you could use jQuery-Animate-Enhanced, which will convert jQuery animate methods to use CSS transitions if they're supported in WebKit, Firefox, and Opera. Of course both this approach and the last one require that you pull in jQuery, so that may not be what you want. However, you could possibly load in jQuery dynamically when you need it, but that would complicate your code flow just a bit. In the end, it's really up to you and how important animation is to your application.
jQuery Plugin as A Namespace
One technique that you might run across is using the jQuery object as a namespace only. For example, this logger method is placed on the jQuery object. Does it use jQuery at all? No. Is it even technically a plugin? No. Why not? Well jQuery plugins define themselves off $.fn, jQuery's prototype so that it could be used after you've selected elements from the DOM. But this library has just attached itself to the jQuery object as a convenient location. There's no real reason or functional benefit to do this. Yes, having a namespace is important to keep down on global variables, but using jQuery's object isn't necessary. My guess is the main reason why this technique is used is because people are familiar with jQuery and since jQuery is very popular, if you attached yourself to jQuery, then it might be more popular as well, or at least more familiar to use. If you did want to define your library off the jQuery namespace, then maybe consider doing something like this, where if jQuery is present, you attach yourself to it. Otherwise, if jQuery is not present, then you create your own namespace and place your functionality underneath it. This is a good compromise because it could keep people familiar with how to use it off of jQuery, of if they don't have jQuery, they could still access it somewhere else. The code will assign jQuery to the local dollar sign, if it's available, otherwise it will use the existing etm namespace, or create a new etm namespace if it hasn't been created yet. That way we'll default to the jQuery namespace or use a custom one as a backup. So if jQuery is on the page, then you could use the logger off of jQuery, or if jQuery isn't on the page, then you could use etm as your namespace and call the logger method off of that. Another way to code the same thing would be like the following. We're still using an IFFE, but this time we're passing in our namespace instead of figuring that out inside. The rest of the code is pretty much the same.
Simple jQuery Plugin
So let's take a look at a really simple jQuery plugin, actually most of the code is commented out because it's not important for what we're going to talk about. This is a little tooltip plugin that will grab the title off any element you provide it, and create a tooltip when you hover over the item. We're obviously using jQuery since it's a jQuery plugin, but if you look closer, we aren't really doing a whole bunch that really needs jQuery. We are adding event handlers, manipulating the styles, changing the text, and things like that, but we can do all those things pretty easily without jQuery, right? Imagine how many other people could use this plugin if it didn't depend on jQuery. Maybe a Dojo person wanted to use this or a Mood tools developer. Or what if someone who didn't want to use any of these libraries at all wanted to use it, wouldn't it be nice to have a bare bones version? Well, that's what we're going to look at doing.
So first let's tackle the extend piece. This utility method is used to merge custom settings onto the default settings. As you heard me mention about this is in a previous module, the code to do this is not trivial and it isn't native. So what we could do is just take each option separately and check their values and default them if needed. It ends up only being several lines of code, so I'm good with that. If you really wanted a slick method, you could also bring in underscore or low dash and use its extend method, but you probably don't want to rely on a whole other library just for the small feature when our previous snippet should do just fine.
The next main piece that needs to be changed is the creation of the tooltip that will be used and shared throughout the plugin. jQuery makes it really easy to build DOM elements, you just wire up some markup and jQuery does the rest. To natively create these elements, we're going to use the createElement method, set its ID and innerText properties, and then append the element to the body. You might be wondering where the code is to set the CSS styles. Well we actually did that in the previous slide when we were manually setting the options and defaults.
Next we need to convert the event handlers, which end up being pretty easy. Instead of using the two parameter version of the jQuery on method, we'll just use the addEventListener method off our element. That's pretty straightforward, which is nice.
Now we need to convert the piece of code updating the text and position of our tooltip. Changing the text isn't a big deal, we could just use the innerText element property for that. However, updating the position is a little trickier. Thankfully it didn't end up too bad. For the tooltip's new top, we're able to take the element's offsetTop and subtract the tooltip's offsetHeight. And for the tooltip's new left, we'll just that to the elements offsetLeft. And then we're done.
jQuery Plugin Wrapper
Alright, here is a web page that will use a jQuery tooltip. If we'll come over here and run our tooltip, we'll see that when we hover over it, we'll actually get the message, and when we come into our code, we'll see that the anchors have a title and we're just pulling off the title and using that as a the tooltip message. Initially we're just going to use the tooltip jQuery plugin, which is jquery.tooltip.js, so we'll take a look at that. And here again we're defining the jQuery plugin off jQuery fn and we're using extend and we're doing a loop here and returning so we could actually have chaining. Inside here we're creating a new tooltip if it doesn't exist and adding our CSS options, adding a couple event listeners, mouseenter and mouseleave. The mouseenter figures out where the tooltip should go and changes its text, and on leave we throw it off the screen so we don't see it anymore, and here are our default colors. So we could take that code and come over here and just make a general library. So here reason IFFE and we're going to pass in a namespace of tooltip. And we'll still have an init, and what it will do is it'll see if the element exists or not. If it doesn't, it'll actually create it, give it an ID and text, and append it to the DOM. Kind of like what we were doing before. And then instead of using extend since that's kind of complicated code and we're not going to use jQuery or underscore or low dash, we'll just manually create our options and check our defaults in a couple lines of code. It's not too hard. We'll see if they passed in something, if they didn't, we'll use the default. And when we wire up, we could just say addEventListener, mouseenter, mouseleave, we'll set our text with innerText. And to set our top and left we'll just do a little bit of math, we'll take our element.offsetTop and subtract our tooltip's offsetHeight. And for the tooltips left, we'll use the element's offsetLeft. And then with the mouseleave, we'll just kick it off the screen again and pretty much that's all there is. If we come back over here, what we'll do is comment out the jQuery plugin and then we'll uncomment the code to actually use our library. Now it's a little more complicated, it's not jQuery ish. We're going to grab all the anchors, initialize our library, and loop over and wire up each of our elements. It will work though if we save it and come back over. We'll see it's being applied. We're using slightly different colors, but that's okay. But let's go one step further, let's take our library, which is good, because now pretty much anyone can use it, and let's create a wrapper around it. And what we're going to do is call it jstip, and now it's really small. It's still a jQuery plugin, we're putting it off of jQuery's prototype, but now we're just initializing our Tooltip library, we're doing a jQuery each, and returning that so it's chainable. And inside each one we're just calling the wire method to set everything up. And that's all there is to it. Now if we come back over here, we can make sure we didn't break anything, and sure enough, the things still work just fine. Now if you're going to create this adaptor, it'd be great if we could just have one file that has the library on top, and then have this adaptor at the bottom. Either do that in your file our use some build system to do it, but that way if you really are targeting to a jQuery developer, then they have all they need in one file instead of having to download two and figure out the right order and all that stuff. And then you'll have your other script, which is just a library by itself, and that could be used by whoever you want. So hopefully you can see the value of separating these out. And you could go one step more, you could make adaptors for other libraries. It doesn't have to be jQuery, but that's just an example.
So, in summary, some jQuery plugins probably shouldn't be jQuery plugins in the first place. And some jQuery plugins aren't plugins at all, they just use jQuery as their namespace. In that case, it'd be nice if jQuery wasn't included on the page, if another namespace could be used instead. Also, it might be good to remove jQuery as a dependency to your plugin if at all possible. That opens up the use of your library to other developers as well who might not use jQuery. In addition, it'd be nice to provide a jQuery plugin adaptor around your generic non-jQuery library, to make it easier for those who do use jQuery to adopt it into their project. This technique can benefit a larger crowd, and you could even make adaptors for other frameworks as well if you wanted.
Elijah Manor is a Christian and a family man. He is a Microsoft Regional Director, Microsoft ASP.NET MVP, ASPInsider, and IE userAgent and specializes in front-end web development. He enjoys...
Released30 Oct 2013