jQuery’s .closest() versus Element.closest()

Spot the Difference from Wikimedia Commons

I recently discovered there’s a major difference between .closest() in jQuery and vanilla JavaScript. It came up because Element.closest(), a fairly recent addition to JavaScript, is not supported in any version of IE or Edge (it was added to Firefox, Chrome, and Safari over the course of the first nine months of 2015). I was using .closest() to detect whether a click while a popup was open was within the popup or not, in order to close the popup when the visitor clicked outside of it. My efforts to fix the functionality on IE/Edge broke it everywhere, and in the process of fixing that I learned more about .closest() than I would have anticipated there was to learn.

In both cases, the idea is that (element A).closest(element B) tells you whether element B is an ancestor of element A (this is also considered true if they are the same element). Therefore (click target).closest(popup) tells you whether the click fell within the popup regardless of whether it also fell inside an element contained in the popup.

The first problem I ran into in switching to jQuery’s .closest() function is that it can only be run on jQuery objects. That is, event.target.closest() will try for the vanilla JavaScript version only; you need jQuery(event.target).closest() to trigger the jQuery version. Depending on what else you’re trying to accomplish you may have to untangle jQuery/non-jQuery conflicts.

The second problem is that these two versions of the same function do not have the same return values. At all. If element B is not an ancestor of element A, Element.closest() will return null; jQuery’s .closest() will return an empty object. My original code had checks like if ( !(click target).closest(popup) ), which fall apart upon switching to jQuery – no matter what, that if condition will evaluate to false, because even empty objects are truthy values in JavaScript.

Instead, I needed if ( $(click target).closest(popup).length === 0 ) to achieve the same logical outcomes. Once I made those changes everything worked again, and this time in IE/Edge as well as the rest.

Official sources: Mozilla Developer Network on Element.closest(), and jQuery API reference on $().closest(). Note on the latter page that while there is deprecation, it is only for the version of closest with two parameters.


At top: “Spot the Difference” image from Wikimedia Commons.

Leave a Reply

Your email address will not be published. Required fields are marked *