Native JavaScript Equivalents of jQuery Methods: Events, Ajax and Utilities

Contributing Editor
This entry is part 2 of 2 in the series Native JavaScript Equivalents of jQuery Methods

Native JavaScript Equivalents of jQuery Methods

This is the final part of my series which follows on from Do You Really Need jQuery? In this article, we’ll look at JavaScript equivalents for the more advanced methods jQuery provides…

Launching Scripts on Page Load

In the dim and distant past, developers would place scripts in the HTML head and use window.onload = start; to launch an initial function. It worked but window.onload only fires after all embedded files such images have been fully downloaded; you might be waiting some time for code to run.

jQuery provides a far more efficient method:

$(start)

The start() function is executed as soon as the HTML has downloaded and the DOM is ready, but it won’t wait for other assets. Behind the scenes, it uses the native DOMContentLoaded event with fallbacks in jQuery 1.x for IE6/7/8:

document.addEventListener("DOMContentLoaded", start);

I used to fret about this sort of nonsense. It’s unnecessary: simply load your script at the bottom of the page just before the closing </body> tag and you’ll know the DOM is ready.

forEach

jQuery allows you to run a custom function on all items in an array. (This includes collections of nodes. Although these may start life as a NodeList, jQuery copies them to an array-like object before they’re returned):

$("p").each(function(i) {
	console.log("index " + i + ": " + this);
});

each is used internally when you apply multiple methods to the jQuery chain. This command would loop all <p> nodes twice:

$("p").addClass("newclass").css({color:"#f00"});

The native forEach is supported in most browsers including IE9+. However, it only applies to arrays so we need to convert NodeLists by looping through all items or using the Array slice prototype:

Array.prototype.slice.call(document.getElementsByTagName("p"));

Ughh. Personally, I prefer a short custom function which can be passed an array, NodeList or object with a callback. It iterates through the items passing each with its index to that function. This example automatically cancels further processing the first time the callback returns false:

function Each(obj, fn) {
	if (obj.length) for (var i = 0, ol = obj.length, v = obj[0]; i < ol && fn(v, i) !== false; v = obj[++i]);
	else for (var p in obj) if (fn(obj[p], p) === false) break;
};

Events

Event handling was awful in the pre-jQuery days. IE6/7/8 implemented a different event model and even those browsers which supposedly followed W3C standards had enough inconsistencies to make development awkward. jQuery still makes events easier to comprehend:

$("#clickme").on("click", function(e) {
	console.log("you clicked " + e.target);
	e.preventDefault();
});

But the native equivalent isn’t too difficult:

document.getElementById("clickme").addEventListener("click", function(e) {
	console.log("you clicked " + e.target);
	e.preventDefault();
});

This won’t work in IE6/7/8 but nor will jQuery 2.x. Most libraries provide a workaround which registers events using the oldIE attachEvent method. Alternatively, if you only require one event of a specific type on a node, simply apply the cross-browser DOM1 ‘on’ methods, e.g.

document.getElementById("clickme").onclick = runSomething;

(Don’t forget to include a line such as e = e ? e : window.event; at the top of your handler function to cope with the oldIE event object). Remember, none of this is required if you’re supporting IE9+.

jQuery provides non-standard types such as ‘focusin’ and ‘live’ events, i.e. matching elements added to the page by future operations will also have the event applied. jQuery achieves this by attaching a handler to a parent element (such as the page body) and analyzing the event object as it bubbles up through the DOM. You can do this yourself — it’s more efficient, uses less code and is standard JavaScript practice, e.g. rather than attaching a hover event to every table row, you attach it to the table, analyze the object and react accordingly.

If you prefer jQuery’s syntax, why not use Remy Sharp’s min.js? It provides the $ selector, chained on events, trigger functionality and forEach support. The total weight: 617 characters for the minified version.

Ajax

When was the last time you developed a project which required XMLHttpRequest, script injection, GET requests, POST submissions, JSON handling and image loading? jQuery handles many situations and, while it’s flexible, you’ll rarely require all those options. Typical jQuery Ajax code:

$.ajax({
	url: "webservice",
	type: "POST",
	data: "a=1&b=2&c=3",
	success: function(d) {
		console.log(d);
	}
});

The native equivalent:

var r = new XMLHttpRequest(); 
r.open("POST", "webservice", true);
r.onreadystatechange = function () {
	if (r.readyState != 4 || r.status != 200) return; 
	console.log(r.responseText);
};
r.send("a=1&b=2&c=3");

There are more options to consider — such as timeouts — so I would suggest wrapping native code in an easy-to-use function. However, you can optimize it for your project and implement some of the nicer XMLHttpRequest2 features such as binary data, upload progress and cross-origin requests which jQuery doesn’t (directly) implement.

Should You Use jQuery?

Only you can make that decision but using jQuery as a default starting point for every project will not necessarily be efficient or lead to elegant code.

jQuery has been immensely useful and was one of the primary reasons for the rebirth of front-end development. However, unlike specialist libraries for handling canvas, SVGs or other focused tasks, jQuery provides a generic set of tools — you’ll never need them all. The browser vendors have caught up and, unless you need to support oldIEs, jQuery is not the essential resource it once was. To put this it context, if you’ve migrated to jQuery 2.0 you probably don’t need jQuery.

I’ll leave you with a link to Vanilla JS; a library used by many of the top web companies which has a modular architecture and is smaller than all its competitors. The site is tongue-in-cheek but illustrates the point beautifully.

Native JavaScript Equivalents of jQuery Methods

<< Native JavaScript Equivalents of jQuery Methods: the DOM and Forms

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Derek

    Good write-up! Substack has a similar article that might be worth checking out as well http://substack.net/weaning_yourself_off_jquery.

  • http://ohdoylerules.com James Doyle

    I made a small library that maps native dom gets to jquery style selectors. So $(“#iddiv”) would be mapped to document.getElementById(“iddiv”).

    https://github.com/james2doyle/saltjs

  • Peter Galiba

    var toArray = Array.prototype.slice, di = document.getElementById;
    toArray.call(di.call(document, “p”)).forEach(function (value, index) {
    });

    • Peter Galiba

      di should be document.getElementsByTagName or document.getElementsByClassName

  • http://www.xysyst.com Sanjeev

    Thanks a lot Craig. :-)

  • I’mYour Father

    I’m still deciding whether to call you out or call you… stupid. “Vanilla” anything is never useful. To be productive you’ll always need libraries.

    I’ve decided I’ll just call you out. Please, pretty please, put all your non-jQuery thoughts together and enlighten us with a “vanilla” JS *productive* library.

    Thank you (?)

    • http://www.optimalworks.net/ Craig Buckler

      You’re missing the point. You don’t need a library because modern browsers provide the core jQuery functionality. A library which smooths over issues which don’t exist won’t make you more productive!

      • I’mYour Father

        You’re completely oblivious to the reusability factor my friend. And you’re also mistaken productivity with performance. Get your coding jargon right.

        By the way, nice Duck Duck Go! I always have a good laugh when coders prove themselves but fail at proving their abilities.

      • http://www.optimalworks.net/ Craig Buckler

        Reusability? What’s not re-usable about document.querySelectorAll, document.addEventListener or CSS3?

        You appear to be living in 2007 where IE6 and 7 rule supreme. At that time, jQuery provided an essential cross-browser compatibility library for JavaScript coders who didn’t have the time or inclination to do it themselves. Times have changed; core incompatibilities are largely non-existent.

        I find it mildly amusing when developers contradict themselves by refusing to support IE6/7/8 then claim they must use jQuery (1.x) because it offers great compatibility with those browsers!

        Finally, I’d love to know how jQuery makes you so much more productive? Is it doing something magical or is it simply because you’re used to the syntax and are nervous about your first tentative steps into native JavaScript?

  • Christos Hrousis

    Thanks Craig,
    Some of us really appreciated your write ups on “no jquery”, even though it caused so much controversy… hahaha.

  • http://scriptvenue.com Arvind

    nice article !!!

  • http://www.layalyeg.com/ layalyeg

    Thank you very cool

  • Michele Pappalardo

    hi Craig, good article.

    can you tell me how could I get a part of file using native JavaScript?

    Using jquery I get #someElement in this way:

    $(div).load(“someFile.html #someElement”);

    thanks