function $(C,P){P=P||document;return/:first$/.test(C)?(P=P.querySelector(C.slice(0,-6)))?[P]:[]:[].slice.call(P.querySelectorAll(C))}
— Andrea Giammarchi (@WebReflection) May 20, 2014
What's New Here
The most tiny, common and probably used utility for quick prototyping is usually even smaller:function $(S,P){return [].slice.call((P||document).querySelectorAll(S))}but it's a performance killer for all cases where we use
#selectors
or even body
since the engine inevitably needs to check all nodes in the DOM.
The Handy :first
Pseudo Selector
Hard to believe W3C preferred two different but similar methods instead of simply adding a pseudo :first
selector which is not standard and on top of it, it does not work as :first-child
or any other selector ... the purpose would be to select only the first occurrence and stop the DOM parsing in an efficient way; instead we need to use querySelector
, which is different from querySelectorAll
.
A Consistent Result
Not only two different methods to use, we cannot operate in a similar way with those results anyway since one is collection like, where thelength
would be the indicator for empty results, while the singular version would be eventually null
.
Well, Scratch That!
With desktop and mobile browsers released between 2008 and today we can do already many things using native APIs and here we have a probably not always perfectqSA
that might fail using some crazy selector I personally try to avoid anyway, plus many Array
extras that today are not extras anymore thanks to any sort of polyfill.Good news is, we might want to polyfill only for jurassic browsers
querySelector/All
too ... so here what we can do:
// set all click actions per each link $('a') .forEach(function (link) { link.addEventListener('click', this); }, function click(e) { // prevent default e.preventDefault(); // and show the link alert(e.currentTarget.href); } ); // only first occurrence $('.logout:first').forEach( ... action ... );
Going Wild Extending
The temptation to extendArray.prototype
in order to simplify listeners handling is huge ... but while I am not telling you some library did it already, I'd like to show some trick to be less obtrusive and still super productive:
// simple utility to add an event listener $.on = function (CSS, parentNode, type, handler, capture) { // in case parentNode is missing if (typeof type !== 'string') { capture = handler; handler = type; type = parentNode; parentNode = null; } return $(CSS, parentNode).map(function (el) { el.addEventListener(type, handler, capture); return el; }); }; // example $.on('a', 'click', function (e) { // prevent default e.preventDefault(); // and show the link alert(e.currentTarget.href); });