Main Menu

Faking the Future

Ah, querySelector, the native answer to the best part of jQuery, or rather Sizzle.querySelector returns the first matching element descended from the element on which it is used. When used as querySelectorAll, it returns the entire list of matching descendant elements. It is elegant, and yet so useful. It’s proof that JavaScript just keeps getting better and better.

document.getElementsByTagName('h1')[0]; // the old way
document.querySelector('h1'); // the new way
someElement.getElementsByClassName('foo'); // the old way, which never worked until IE9
someElement.querySelectorAll('.foo'); // the new way, which even works in IE8

What bums me out about querySelector is that it implies some other APIs that are missing. For example, if we wanted to check whether an element is matched by a selector, we would use matchesSelector. That kind of functionality would be especially useful in event delegation where the returning target is unknown. Unfortunately, matchesSelector is unavailable in IE8, Safari 4, and, as of mid-2012 exclusively vendor prefixed while the Selectors API 2 remains a draft.

UPDATE:: A previous version of this article used Array.prototype.indexOf, to polyfill matchesSelector which was then also polyfilled for Internet Explorer 8. Unfortunately, doing this would make indexOf enumerable on all arrays, and that would be super annoying.

With matchesSelector polyfilled, we can check whether an element matches a selector. Using querySelector we can return a descendant matching a selector. Now, what if we wanted to get an ancestor that matched a selector, similar to jQuery’s closest() method? we would need an ancestorQuerySelector method. ancestorQuerySelector would return the first matching ancestor of the element on which it is used. When used as ancestorQuerySelectorAll, it would return the entire list of matching ancestor elements.

Unfortunately, ancestorQuerySelector doesn’t have a native implementation in any browser. So, if we were to add it? And what if we were to check for native or vendor-prefixed functionality first? Is that still polyfilling? Can a developer make such a suggestion without writing a selector draft? Are we faking the future or fauxing the future?