Appendix B. Native equivalents of common jQuery functionality

In chapter 8, I discussed the importance of embracing minimalism in your website’s JavaScript. A way of getting there is to drop jQuery altogether and use what’s available in the browser. This appendix highlights some common jQuery functions and then shows you how to accomplish the same tasks by native means. This isn’t a complete reference. Such a thing would be far beyond the scope of an appendix. This is to get you started.

B.1. Selecting elements

jQuery’s core $ method selects DOM elements by using a CSS selector string like so:

$("div");

This selects all <div> elements on a page. Generally speaking, whatever valid CSS selector that works in the $ method will work with document.querySelector and document.querySelectorAll (excluding any custom selectors specific to jQuery). The difference between them is document.querySelector returns only the first matching element, whereas document.querySelectorAll returns all matched elements in an array object, even if only one element is returned. This listing shows examples, with return values annotated.

Listing B.1. Using querySelector and querySelectorAll

Although these two methods are useful, other methods are more widely supported and are faster when it comes to selecting elements. They’re shown in table B.1.

Table B.1. jQuery versus native element selection methods

Selector

jQuery code

Native equivalent

ID $("#element"); document.getElementById("element");
Tag $("div"); document.getElementsByTagName("div");
Class name $(".element"); document.getElementsByClassName("element");

These core element selection methods are supported in virtually all browsers, and are great for selecting elements when their presence in the DOM is known and predictable. More-complex selections should be made using the aforementioned querySelector methods.

B.2. Checking DOM readiness

This is covered in chapter 8, but I’ll recap it here for reference purposes. Before you can do anything in jQuery, you must check whether the DOM is ready. Otherwise, jQuery code will fail to execute properly. The common way to check for DOM readiness in jQuery is shown here:

$(document).ready(function(){
    // Code goes here
});

You can use an equivalent shorthand method if you want to save a few bytes:

$(function(){
    // Code goes here
});

If you prefer to use plain old JavaScript instead of jQuery, you can check for DOM readiness by listening for the DOMContentLoaded event via addEventListener, like so:

document.addEventListener("DOMContentLoaded", function(){
    // Code goes here
});

This is supported since IE9. In older browsers, though, you need to go a different route:

document.onreadystatechange = function(){
    if(document.readyState === "interactive"){
        // Code goes here
    }
};

If you’re going to go without jQuery and you don’t know which DOM readiness method to use, go with document.onreadystatechange. It has wide support and works much the same way as listening for the DOMContentLoaded event with addEventListener.

B.3. Binding events

Next to element selection, jQuery’s biggest strength is its event-binding syntax. This little section shows common jQuery event-binding methods, and how to achieve similar functionality without jQuery.

This section isn’t an event reference!

This section isn’t an exhaustive reference of all events you can use in either jQuery or in native JavaScript APIs. For a reference of available events to plug into addEvent-Listener, check out this event reference from MDN: https://developer.mozilla.org/en-US/docs/Web/Events.

B.3.1. Simple event binding

jQuery listens for events on elements by using the bind method (which has been deprecated since jQuery v3 in favor of on, which is shown later in this section). Here’s a simple example of executing some code when an element is clicked:

$(".click-me").bind("click", function(){
    // Click event code goes here
});

jQuery also has shorthand methods that look a bit cleaner than using bind. The following code accomplishes the same task:

$(".click-me").click(function(){
    // Click event code goes here
});

You can achieve the same thing by using querySelector and addEventListener like so:

document.querySelector(".click-me").addEventListener("click", function(){
    // Click event code goes here
});

Most of the time, you should be able to take the same event names used in jQuery’s bind syntax and plug them into addEventListener, but don’t assume that you can for anything but the most basic events. Check out the Mozilla Developer Network’s web event reference for a list of events you can use.

B.3.2. Triggering events programmatically

Sometimes you’ll have event code bound to an element that you want to trigger programmatically within your JavaScript code. Let’s assume that you still have the same click event code bound to the .click-me element, and you want to run the click event code bound to it on demand. Using jQuery’s trigger method, you can do that:

$(".click-me").trigger("click");

This statement will run the click event code bound to the .click-me element—nice if you need to run event code attached to an element on demand. You can accomplish the same task without jQuery via the dispatchEvent method.

Listing B.2. Triggering events programmatically without jQuery

This syntax isn’t as compact as jQuery’s, but it works. You could shorten this by creating a helper function that eliminates the tediousness of creating new Event objects.

Listing B.3. An event-triggering helper function
function trigger(selector, eventType)
    document.querySelector(selector).dispatchEvent(new Event(eventType));
}
trigger(".click-me", "click");

The triggering function in the listing selects the element with a given selector, and triggers a specified event. It’s not often that you’d need to trigger events outside the context in which they were bound to elements, but it’s possible to achieve this functionality without jQuery.

B.3.3. Targeting elements that don’t exist yet

jQuery can bind to elements that don’t exist by using the on method. This is useful when you need to impart functionality to elements that don’t exist now but may exist in the future. Here’s an example of this method executing code on <li> elements within a <ul> element:

$(".list").on("mouseover", ".list-item", function(){
    // Mouseover code goes here
});

With this code, any .list-item elements added to the .list element in the future will still execute the code bound to the mouseover element. You can imagine all sorts of scenarios where this would be useful, and you can do the same thing without jQuery via the following code.

Listing B.4. Binding behavior to elements that don’t exist yet without jQuery

Again, not as compact as jQuery, but functional. Of course, if you’re targeting child elements with something other than a class, you may need to poke around in the event.target object for other methods to target child elements by. For example, you can use the event.target.id property to target elements by ID, or the event.target.tagName property to target elements by their tag name. It’s not as convenient or compact as jQuery’s syntax, but it works.

B.3.4. Removing event bindings

jQuery can remove bindings from an element by using the unbind and off methods like so:

$(".click-me").unbind("click");
$(".list").off("mouseover", ".list-item");

Like bind, unbind has been deprecated since version 3 of jQuery, so using off is preferable going forward. In either case, you can use removeEventListener in regular JavaScript to remove an event binding on an element:

$(".click-me").removeEventListener("click", boundFunctionReference);

When you remove an event binding with removeEventListener, you have to provide the function that you bound to it in the first place. In this case, boundFunction-Reference is a placeholder for the function you’d have bound to an element with addEventListener.

B.4. Iterating over a set of elements

jQuery gives you a super helpful method for iterating over a set of matched elements in the form of the each method. You can run it on any set of matched elements:

$("ul > li").each(function(){
    $(this); // The current element in the iteration
});

Doing this without jQuery is easy. Just use a for loop as shown next.

Listing B.5. Iterating over a set of elements without jQuery

Another way of looping over a set of matched elements also uses the for construct, but in a different way:

for(var i in listElements){
    listElements[i]; // The current member in the iteration
}

Beware of this syntax, however: it loops over not only all elements in the set, but also object members such as the length property. Most of the time, you won’t want to use this syntax, but you may conceive of scenarios where it’s desirable.

B.5. Manipulating classes on elements

jQuery allows you to manipulate classes on elements by using the addClass, removeClass, and toggleClass methods.

Listing B.6. Manipulating element classes with jQuery

A native class-manipulation API called classList provides much of this functionality. The following are classList-driven equivalents of the jQuery methods shown previously.

Listing B.7. Manipulating element classes without jQuery

You can also supply a condition as a second argument to the toggle method. If the condition evaluates to true, the class is added. If the condition evaluates to false, the class is removed.

Listing B.8. Conditionally toggling classes using classList

classList doesn’t have universal support, however, and all versions of IE since IE10 only partially support it. For example, the second argument for the toggle method shown in the preceding code isn’t supported in any version of IE. In this case, you can always manipulate the selected element’s className property. You can easily add a class to an element just by concatenating a string to that property:

item.className += " new-class";

Removing/toggling classes is more involved. It usually involves using a regular expression or expanding a className property into an array and manipulating it that way. If you need to do more than simple class addition in the absence of classList, consider using a polyfill. One is available at https://github.com/eligrey/classList.js that weighs in at a little over 2 KB minified. Server compression can reduce the weight of this polyfill even further.

Sometimes you might need to check whether an element has a particular class. jQuery features the hasClass method, which affords you this ability:

$(".item").hasClass("item"); // Returns true

The easiest way to do this is to use the classList contains method.

Listing B.9. Checking for an existing class with classList.contains

For browsers without classList support, use the polyfill noted previously. Otherwise, you could write your own code to check for the existence of a class.

B.6. Accessing and modifying styles

jQuery allows you to access and modify element styles by way of the css method. You can get or set a single CSS property in jQuery.

Listing B.10. Setting styles with jQuery

You can also set multiple CSS properties on an element with the CSS method:

$(".item").css({
    color: "#f00",
    border: "1px solid #0f0",
    fontSize: "24px"
});
Note

When setting CSS properties on elements, remember that properties with dashes aren’t expressed the same way when used in the context of an object. font-size becomes fontSize, border-bottom becomes borderBottom, and so on. The hyphen character isn’t a legal character in variable names because it’s a language operator. This convention also exists in native JavaScript, not only jQuery, so be wary.

Getting/setting styles without jQuery is more involved. If you want to retrieve a CSS property set on an element, you need to use the getComputedStyle method.

Listing B.11. Getting an element’s style without jQuery

Setting styles requires using the style object:

item.style.fontSize = "24px";

What if you want to set multiple styles? You could set them all at once via the HTML style attribute:

item.setAttribute("style", "font-size: 24px; border-bottom: 1px solid #0f0;");

This may seem a bit unsightly for some, but it’s high-performing. If you don’t care, and still want something a bit nicer looking, you could create a helper function like the one shown in the following listing that uses a similar syntax to the way jQuery’s css method sets multiple CSS rules.

Listing B.12. A helper function for setting multiple CSS properties without jQuery

You can read properties set by the style object, but they’ll be populated only if they’ve been previously set. If they haven’t been, you’ll get an empty string. In this case, use getComputedStyle as shown previously.

B.7. Getting and setting attributes

jQuery’s attr method allows you get and set attribute values like so.

Listing B.13. Setting attributes with jQuery

Setting them in plain old JavaScript couldn’t be much simpler.

Listing B.14. Setting attributes without jQuery

If you want to set multiple attributes in one go, you can use something similar to the code shown in listing B.8:

function setAttrs(element, attrs){
    for(var attr in attrs){
        element.setAttribute(attr, attrs[attr]);
    }
}

setAttrs(document.querySelector(".item"), {
    style: "color: #333;",
    id: "uniqueItem"
});

The setAttribute and getAttribute methods have nearly ubiquitous support, so they can be used without too much concern over compatibility.

B.8. Getting and setting element contents

jQuery has two methods for getting and setting element contents: html and text. The difference between the two is that html retrieves element contents with markup, and when used to set element contents, will treat markup literally. text strips out markup, and when used to set element contents, will treat text literally and encode any markup-related characters as HTML entities. The following listing shows how jQuery gets and sets element contents with these methods.

Listing B.15. Getting and setting element contents with jQuery

These methods have similar equivalents in native JavaScript: innerHTML and innerText, and they’re used as shown in the following listing.

Listing B.16. Getting and setting element contents without jQuery

A caveat: innerHTML is considered a standard property, but innerText isn’t (even though a lot of browsers support it). innerText is aware of styling in that if elements with another element are hidden by CSS, innerText won’t include the hidden element’s contents in its return value. If this is problematic for you, you can use the text-Content property instead.

Listing B.17. Setting an element’s text content

innerHTML is the gold standard of getting or setting element contents if you want to include HTML, but if you’re in doubt over which to use for getting or setting element text, default to textContent. It’s well supported, with the exception of IE8 and below; innerText is supported in IE6 and above.

B.9. Replacing elements

jQuery has a replaceWith method that, unlike html, allows you to replace the entire element itself with whatever content you’d like, rather than just its inner contents:

$(".list").replaceWith("<p>I don't like lists.</p>");

With this code, the .list element is replaced with a new <p> element. As it turns out, an outerHTML element has been supported in browsers for a while that does the same thing:

document.querySelector(".list").outerHTML = "<p>I don't like lists.</p>";

Doesn’t get much easier than that. outerHTML has been supported since IE4. Yes, you read correctly: Internet Explorer 4. Other browsers have supported it either since their inception, or many moons ago, so use it with confidence. An outerText property works like innerText, but replaces an element with whatever text you provide:

document.querySelector(".list").outerText = "<p>I don't like lists.</p>";

This replaces an element entirely with the supplied text, and will encode HTML characters so that they appear literally, with no interpretation made by the browser. Unlike outerHTML, however, outerText isn’t a standard property. It’s supported in every browser except for Firefox, so use it with care.

B.10. Hiding and showing elements

This one is super easy. jQuery has two methods for hiding and showing elements, named hide and show, respectively. They work like so:

$(".item").hide();
$(".item").show();

You can achieve the same functionality by using the element’s style object.

Listing B.18. Hiding and showing elements with the style object

Of course, you should bear in mind that using a display value of block may not always be the best idea. Maybe you’re toggling an element that uses a display type of flex, inline-flex, inline, or inline-block rather than block. In cases like these, it’s best to have a global utility class that hides elements like this:

.hide{
    display: none;
}

Then you can just use a classList method to add or remove this class. When the hide class is added to an element, it will hide it. When it’s removed, the element’s original display property value will kick in. This prevents unintended layout problems.

B.11. Removing elements

Sometimes an element just needs to go. jQuery gives you a nice method for it named remove. It works like this:

$(".item").remove();

This removes every element with a class of item from the DOM. A method in native JavaScript goes by the same name and works similarly. Try this on for size:

document.querySelector(".item").remove();

The problem here is that querySelector returns only the first item that matches the query. You can use querySelectorAll, but the return value for it is an object array. Therefore, if you want to remove all items that match the query, you need to iterate over the set of matched elements as shown in the following listing.

Listing B.19. Removing multiple elements from the DOM without jQuery

The same code must be used with any element selection method that returns an object array (for example, getElementsByTagName, getElementsByClassName), not just querySelectorAll. Things are much more straightforward if you need to use only getElementById or querySelector, as you can call the remove method directly on the selected element rather than having to iterate over a set of them.

B.12. Going further

You can achieve a lot more via native JavaScript means in lieu of jQuery than what’s documented here. A great place to check out is the You Might Not Need jQuery website at http://youmightnotneedjquery.com. It has a slew of code snippets of common (and not so common) jQuery behaviors and their native equivalents. It also allows you to specify the level of browser compatibility you need. If something is missing here, give that site a look. Failing that, look to Google! Someone out there has figured it out, and it’s out there!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset