
Bling – the $ of jQuery without the jQuery - kolodny
https://gist.github.com/paulirish/12fb951a8b893a454b32
======
ceronman
Yes, you can re-implement jQuery in 10 lines of code... if you only support
0.1% of the functionality of jQuery.

jQuery was a game changer for web client side development. Thousands of work
hours have been spent on it. It had a specially important role of dealing with
all the inconsistencies between browsers. If you don't use all the features,
nowadays you can just create a custom build with the stuff you want.

If you don't need jQuery, maybe because you only care about modern browsers,
or you use another library or you don't mind a bit of extra boilerplate for
DOM manipulation, that's perfectly fine. But these kind of posts seem like
mockery on the developers of a library that has provided extreme value for
thousands for developers over many years.

~~~
inglor
You are arguing against a strawman - no one is claiming otherwise. All
paul_irish wanted to show is that people often use jQuery without realizing
that most of what they do is also possible with the current browser APIs.
jQuery does a ton more (animation, ajax etc) - the point was not to "rewrite
jQuery in 10 lines" (that's Zepto)

~~~
nolok
Zepto is more of a "provide the jquery interface you're used to" (and that
people often find easier, probably by habit) for modern browsers without all
the added compatibility in jquery. I don't like the way they present
themselves (or at least did in the early days) but I believe they have a
place.

~~~
frik
I tried "Flot" charts library with zepto as a smaller replacement for JQuery,
but it was incompatible with JQuery and uses a weird code style that is
incompatible/slow with Firefox (and Zepto devs refuse to fix their code). In
the end I replaced the few Jquery dependencies in Flot by hand. It's a shame
that Flot still requires Jquery, it's a good charts library.

 _The primary problem is that the zepto.Z function overrides dom.__proto__,
which prevents many JIT optimizations. Overriding an object 's __proto__
property is strongly discouraged and will be deprecated in ES6_ \--Firefox bug
947048

------
addicted44
If you are using $ signs all over your code, they'd better refer to jquery and
nothing else.

jQuery has, for better or worse, become such an integral part of web
development, the $ namespace is pretty much owned by it at this point.

If you do want to use it for not-jquery, it should be something that is
drastically different so someone new trying to patch a bug on prod doesn't run
around in circles wondering why their code that should be working is not.

The bling.js project by repurposing $ into something that looks like it might
be jquery but isn't, is just a bad idea.

~~~
untog
It's not even a project, it's a GitHub Gist. Talk about a lot of fuss being
made over nothing.

~~~
wwweston
Sure, this is just an illustration. I hear Eric Meyer's normalization css was
too -- more intended as a to-do list of elements you might want to consider
reseting than something to include and then override. But then a lot of people
ran with the idea of leveling all margins and padding with a global override
to start with and then overriding that override (usually inadequately).

Of course, the horse is out of the barn on the personal $ library front, so
maybe Irish doesn't have to worry about inadvertently influencing people
badly. There already was a no-library/micro-library trend 4-5 years ago where
lots of people would write their own tiny jQuery-like DOM utilities, and I've
worked on a few projects where someone used jQuery-like idioms for their
partial reimplementation (I call them "nayQuery"). Even the better ones are a
pain where they subvert expectations. And of course, when someone later
decides to add jQuery to the project (makes sense, jQuery does more and has an
ecosystem around it), now you're using $ for the custom library and jQuery for
jQuery, which is disorienting.

I've written my own version of what Irish presents here -- it's a useful
exercise, I appreciate his contribution (helps me think about some different
ways to approach it), and sometimes it's even concretely useful when you're
getting started on a small project with a limited browser target where the
rest of the codebase is going to be smaller than jQuery itself.

But when I write something like this, I _always_ name it differently than $.

------
pluma
This does three things:

1\. Alias document.querySelectorAll to $. 2\. Alias node.on to
node.addEventListener. 3\. Make NodeList a sub-type of Array (so you can use
forEach etc on node lists as you would on arrays).

The $ of jQuery also does a few other things, e.g. create HTML elements from
text ($('<div class="foo"/>') creates a div element with CSS class "foo") and
wrap elements in a node list ($(document.body) creates a node list containing
document.body).

~~~
pimterry
4\. Add NodeList.on, which adds the event listener to all nodes in the list

~~~
masklinn
Without the eminently useful support for delegation.

~~~
numbnuts
This fork[0] adds delegation.

[0]:
[https://gist.github.com/MadeByMike/7e7707eff116229a5948](https://gist.github.com/MadeByMike/7e7707eff116229a5948)

------
yakshaving_jgt
“jQuery is not need anymore with modern browsers.”

Bull. Shit.

This document proves why, and is written by the _same guy_ that is now pushing
this “you don’t want jQuery!” stuff.

[https://docs.google.com/document/d/1LPaPA30bLUB_publLIMF0Rlh...](https://docs.google.com/document/d/1LPaPA30bLUB_publLIMF0RlhdnPx_ePXm7oW02iiT6o/edit#)

~~~
BinaryIdiot
>> “jQuery is not need anymore with modern browsers.”

> Bull. Shit.

Depends on the target environment(s). If you only want to support evergreen
browsers then there is no reason you need jQuery; you're going to have the
native DOM APIs and you don't care about compatability.

jQuery's big win is two fold, in my opinion. One it has awesome, chain-able
syntax and two (most important) it has awesome backwards compatibility with
terrible browsers. If you don't need two then is one worth bringing in another
dependency? Maybe or maybe not.

~~~
yakshaving_jgt
> If you only want to support evergreen browsers then there is no reason you
> need jQuery

False.

Read the _first sentence_ of the document I linked to.

“…developers should be aware that ditching libraries, like jQuery, can easily
require large amounts of research on their end to avoid bugs ( __even in
modern browsers __).”

Bear in mind it’s _Paul Irish_ who wrote that.

~~~
BinaryIdiot
> False

> Read the first sentence of the document I linked to.

Oh I did. Look through many of the bugs they outline; many are incredibly
minor and inconsequential unless you're doing things related (or semi related)
to supporting older browsers.

> Bear in mind it’s Paul Irish who wrote that.

Yup; I don't see his posts being quite in conflict like many here seem to
think. Plus his opinion has probably evolved overtime anyway (he wrote that
document a year and a half ago).

------
vortico
This is all I personally ever need.

    
    
      function $(q) { return document.querySelector(q) }

~~~
zodiakzz
I prefer:-

    
    
      function $(q, parent) { return (parent || document).querySelector(q); }

~~~
egeozcan
I'd also wrap it in a `[].slice.call`:

    
    
        function $(q, parent) {
            parent = parent || document;
            return [].slice.call(parent.querySelectorAll(q));
        }

~~~
marcoms
Also see ES2015's Array.from()

    
    
        Array.from(<NodeList or other iterable>)
    

[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)

------
goyote8
Can someone explain the new trend to not use jQuery?

~~~
aethr
A lot of developers originally used jQuery as a cross-browser compatibility
library when that was still a major concern. Along the way, jQuery has added
tons of extra helper functions and wrappers (ie, .ajax(), .post(), event
binding helpers, etc). This has been amazing for web development, but it's
also been such a major pillar of web development that a lot of front end
developers don't actually know what's happening under the hood when they use
jQuery.

jQuery as a library has now become huge, and a lot of projects probably don't
use the full feature set. With modern browser support converging and older
browsers being edged out of the usage stats, there's not as much need for the
cross-browser portions of the library anymore. Enough so that newer versions
of jQuery have dropped support for those browsers as well.

So if you can cut down your cold cache loading times by not including the full
jQuery library, that's probably a win (especially on mobile). You can do this
by using a custom build of jQuery, but I guess some developers are taking this
opportunity to go "back to their roots" and see how Javascript has changed
since jQuery became a de-facto include in every project.

I think there's a lot more maturity in the language these days, and by using
native JS methods there's probably opportunities there for browser
optimisations that aren't available using helper methods written in JS that
accomplish the same functional goals.

But I'm not a browser devevloper or a JavaScript expert, just a long time web
developer who remembers the times before jQuery was in every project. If it's
a crutch, it's one I will remember fondly.

~~~
gabemart

      > jQuery as a library has now become huge
    
      > So if you can cut down your cold cache loading times by not
      > including the full jQuery library, that's probably a win
    

jQuery 1.11.3 is 38.4 KB when minified and gzipped.

jQuery 2.1.4 is 34.1 KB when minified and gzipped.

I'm all for eliminating unnecessary bloat, but it's not as if a jQuery
download is a huge amount of data to fetch. While jQuery is not a framework,
most front-end JS frameworks are the same size or bigger and don't receive as
much attention for being bloated.

If you can get by without jQuery, or if you have a very large number of mobile
users and first-load performance is mission-critical for your application, or
if you have a large percentage of users from countries with slow or
intermittent internet connections, then sure, avoiding jQuery makes sense as a
priority. But for most applications, jQuery is a smaller download than a
single medium-resolution highly optimized image, and it can be cached forever.

~~~
bad_user
Loading over 30 Kb of minified/gzipped Javascript over a 3G connection on a
mobile phone is very problematic, as the bandwidth is poor, the CPU capacity
for decompressing and parsing is poorer than on the desktop, so the latency
can many times be measured in seconds, therefore loading over 30 Kb of stuff
that you don't need gets to be a tough pill to swallow. Also the argument of
caching is often brought up, but in my tests this can be very non-
deterministic, as mobile phones are pretty aggressive in their used storage.
JQuery is supposed to be cached, yet in our A/B testing the load times and
consequently the conversion rates improved greatly after we dropped JQuery.

Your comparison with "a single medium-resolution highly optimized image"
doesn't hold for mobile phones. On mobile phones users expect latency when
loading images, but not when loading the UI. Another problem is that JQuery is
not the only commonly used library. You add Underscore, you add Angular, or
whatever libraries du-jour we have and pretty soon we are talking about 100 Kb
of stuff or even more that is rarely used as a whole.

Of course, my use-case is about having really simple interfaces augmented by
Javascript and meant for mobile phones. Well, for complex interfaces I think
bringing in JQuery as a dependency may be worth it, but then again, I then
start thinking that JQuery is not enough. It's because I want more, I want a
virtual DOM that's saner by design, I want to work with immutability, I want
much better performance without unpredictable behavior (like what you get with
Angular) and I want to only pay for the features I use. JQuery is incompatible
with React and is incompatible with Google Closure in advanced mode.

~~~
copsarebastards
It sounds like you've done the work to validate the fact that 30Kb is too much
for your use case.

However, let's be clear here: most people who complain about the size of
jQuery are doing so without any basis whatsoever. And even if people are
measuring, they may not be measuring the right things. If not using jQuery
causes you to reduce your Ajax usage, and reload entire pages as a result
instead of only reloading the content, the end result is a slower site.

~~~
bad_user
I totally agree and I exposed my use-case - really simple interfaces augmented
by Javascript and served to mobile phones, so JQuery was basically unneeded,
taking it out improved latency and thus it improved conversions. But of
course, most people don't measure and most people need the features in JQuery
to work reliably and to behave well cross-browser, in which case 30 Kb cached
by a CDN is a steal.

------
shekel
My worry about using this is you'd better be damn sure you never actually use
jQuery or libraries that integrate with jQuery if you're going to use it. I
think this is a cool demonstration of the difference between some of the
"convenience" functions of jQuery many are familiar with and the MEAT of
jQuery which is the functionality and cross-browser issue smoothing.

------
eloisant
I don't really know what to think about that.

On one hand it may be a nice way to show to people that what they use in
jQuery can be written in a few lines of pure JS.

On the other hand it encourages people who could use pure JS (because they
only use a small portion of jQuery) to stick with some non-standard helper
syntax.

~~~
andybak
> to stick with some non-standard helper syntax.

Or in other words - replacing an ugly, verbose API with a widely recognised
alternate syntax!

~~~
anton-107
Yes "document.querySelectorAll(selector)" is a bit verbose, but jQuery API is
no better, do you know what would "$(selector)" actually do? You can't - it
depends on what "selector" is.

~~~
yakshaving_jgt
> "document.querySelectorAll(selector)" is a bit verbose

Right. 35 characters.

> "…but jQuery API is no better"

Your jQuery example is 11 characters.

I can’t believe you’re using verbosity as a measurement, while at the same
time claiming 35 and 11 are the same.

Does. Not. Compute.

~~~
anton-107
Sorry for confusion, what i meant was: yes DOM API is a bit verbose, but
jQuery is exactly the opposite in a bad sense: it's using too few words to
express too many different things.

~~~
Akkuma
jQuery uses CSS selectors, which is fairly clear if you have a general
understanding of them.

~~~
anton-107
So does querySelectorAll, that's not the issue with jQuery API.

The problem is that "jQuery" function, aliased as "$" has 9 signatures (doing
9 different things, depending on which arguments you send to it), while
querySelectorAll does only one thing

------
XCSme
Well, the thing with jQuery is that if you use a CDN to get it from, then it
is a very high chance that the client already has the library cached, so the
bandwidth problem is actually not that much of a problem now.

~~~
LocalPCGuy
It's probably better for most sites to minimize the number of DOM lookups by
combining jQuery with the rest of your vendor code in a vendors.js (or
similar) file. The chance for a cache hit is very low (and getting lower with
the trend away from jQuery).

That said, test the 2 approaches and see which works better for your site.

------
Kiro
> [].slice.call( document.querySelectorAll('.foo'), function(){

When do you need to do that?

~~~
renekooi
querySelectorAll returns a NodeList instead of a real array, so you can't call
things like `.forEach` on the result. `[].slice.call(x)` turns x into an
array, so that becomes

    
    
        [].slice.call(document.querySelectorAll(...)).forEach(function () {})
    

Because a lot of array methods are "generic", i.e. operate on array-like
objects instead of just arrays, that can be "compacted" to

    
    
        [].forEach.call(document.querySelectorAll(...), function () {})
    

but neither are very nice.

------
nateabele
Here's an idea for a jQuery replacement: a website that allows you to select
what browsers/versions you want to support, then it generates you a polyfill.

Then aliases `$` as a selector function.

------
mattdlondon
Shameless self promotion for something I threw together ages ago and may be
implemented in a better way these days.
[https://github.com/matt1/doc.js](https://github.com/matt1/doc.js)

So it uses "doc" instead of "$" but feel free to fork :-)

------
EugeneOZ
When some part of jQuery can be replaced by native APIs so easy, it only shows
how good jQuery was designed.

------
awalGarg
I wrote a similar small dom module[0] which also fits in a gist with docs and
tests :P --shameless-self-plug

[0]
[https://gist.github.com/awalGarg/8a0e18c6fe87456d885f](https://gist.github.com/awalGarg/8a0e18c6fe87456d885f)

------
franciscop
Then you have the "" of jQuery: [http://www.francisco.io/fun-extending-native-
javascript-stri...](http://www.francisco.io/fun-extending-native-javascript-
string)

------
inglor
Note that work is being done to give `NodeList`s the `Symbol.iterator`
property so in new browsers it's trivial to use the native DOM with `for(let x
of nodeList)` loops making our lives easier.

This will make our lives easier :)

~~~
notNow
But I must say that I don't really like the list comprehensions syntax in
JS.It leaves a lot to be desired.

------
etjossem
If you quite literally want "what jQuery uses to select things" and nothing
else, you're really looking for Sizzle.

[http://sizzlejs.com/](http://sizzlejs.com/)

~~~
paulirish
These days it's not Sizzle, which is mostly support for non-qSA browsers and
support for custom pseudo-selectors. jQuery's modern element selection is
[https://github.com/jquery/jquery/blob/master/src/selector-
na...](https://github.com/jquery/jquery/blob/master/src/selector-native.js)

~~~
etjossem
Nice, thanks for the update.

------
nickysielicki
I use jquery because I use bootstrap and it requires it for some features I
use.

I wish that someone would write a drop-in javascript replacement for jquery in
the context of bootstrap.

~~~
nathell
There's zepto.js, which is supposed to be a drop-in replacement for jQuery.
Not sure how it fares wrt Bootstrap, though.

~~~
eatonphil
It is easy enough to just write a shim. Google "bootstrap zepto shim" to get
you started.

------
joesb
Nice. So where is my $.text(), $.css(), $.html(), $.val(), $.first(),
$closest(), etc.?

~~~
izolate
With bling.js:

    
    
        .text: $('.selector')[0].textContent
        .css $('.selector')[0].style
        .html: $('.selector')[0].innerHTML
        .val: $('.selector')[0].value
        .first: $('.selector')[0]
        .closest: n/a

~~~
joesb
jQuery's $.text/html() set the text of all matched nodes, not just the first
one.

I can use key-value object to assign multiple css property, and it can set the
style on all matched nodes.

If there are no matched elements, Bling's $()[0].xxx = value" will raise
exception.

~~~
izolate
That's the thing, Bling.js also makes it easy to set the text/css on all
nodes:

    
    
        $('.foo').forEach(el => el.textContent = 'bar')
        $('.foo').forEach(el => el.style.top = '0px')

------
omegote
Tries to play it cool by wrecking jQuery? Check. No semicolons? Check. Put
together by Paul Irish? Check.

Yep, this submission is Hipster 1.0 Certified.

~~~
VeejayRampay
1) Paul Irish is a former jQuery team member and he has blog entries about how
much he's learned from reading jQuery's source code, not sure exactly how he's
"wrecking jQuery".

2) Semicolons are still in debate amongst the JS community, I don't think
there's a consensus on whether they're needed or not and it seems to boil down
to personal preferences.

3) This reeks of ad hominem, how exactly is Paul Irish "hipster"? Strikes me
as someone who's done a lot of work to make the web a better place for all of
us, fine with me.

~~~
riquito
> 2) Semicolons are still in debate amongst the JS community, I don't think
> there's a consensus on whether they're needed or not and it seems to boil
> down to personal preferences.

They are needed.

This

    
    
        var func = function(x) { console.log(x); };
        func;
        (42);
    

is different from this

    
    
        var func = function(x) { console.log(x); }
        func
        (42)

~~~
bakabaka9
They aren't needed at all. Semicolons in JS are optional.

Knowledge about how ASI works, on the other hand, is mandatory.

~~~
BinaryIdiot
> They aren't needed at all. Semicolons in JS are optional.

So they're not really _optional_. What they are is necessary and if omitted
the engine attempts to put them in automatically. The rules for automatic
semicolon insertion are in section 7.9 of the ECMAScript 5 standard
([http://www.ecma-international.org/publications/files/ECMA-
ST...](http://www.ecma-international.org/publications/files/ECMA-
ST/Ecma-262.pdf)).

This means you're omitting something that is required by the _engine_ but not
necessarily required in the syntax which boils down to you losing control of
where semicolons end up possibly making your code do something you did not
intend because you either misunderstood the rules of automatic semicolon
insertion or there was a bug in the syntax parser being used.

~~~
bakabaka9
You're only "losing control" if you don't know how ASI works, which is well-
defined in the ECMAScript standard.

Bad programmers that can't understand ASI will be also confused by the
floating point semantics, promises and other basic concepts — there are many
ways of "making your code do something you did not intend" in JS, but that's
no excuse for bashing language features.

Fact check: ASI is a fully legitimate part of the language (as in, it's in
standard, it's documented, and supported across the board), so demonizing it
is every bit as silly as e.g. deprecating C macros.

Learning the language helps with the the issues you outlined, while magical
thinking ( _uguuu, semicolons good, no semicolons bad, uguuu_ ) for the most
part doesn't.

~~~
BinaryIdiot
> Bad programmers that can't understand ASI will be also confused by the
> floating point semantics, promises and other basic concepts — there are many
> ways of "making your code do something you did not intend" in JS, but that's
> no excuse for bashing language features.

This is a terrible attitude. There is no reason you may not understand every
case in which a semi colon is automatically inserted but can still understand
floating point, promises and other things. Automatic semicolon insertion isn't
really a "basic concept"; it's a convenience for those who elide them and
nothing more (the ECMAScript 5 standard even states this).

> Fact check: ASI is a fully legitimate part of the language (as in, it's in
> standard, it's documented, and supported across the board), so demonizing it
> is every bit as silly as e.g. deprecating C macros.

I'm not "demonizing" it but if you look at the standard the engine still
_requires_ semicolons it just fills them in for you if you miss them. This is
vastly different than your deprecation of C macros example. Yes it's
documented but it's non-obvious unless you've literally looked it up to learn
it. I'm also not sure why you insisted on letting me know it's a "fully
legitimate part of the language (as in, it's in standard, it's documented, and
supported across the board" when I linked to the standard and stated exactly
where to look for its definition...

> Learning the language helps with the the issues you outlined, while magical
> thinking (uguuu, semicolons good, no semicolons bad, uguuu) for the most
> part doesn't.

Sigh. Automatic semicolon insertion is only documented. There are no errors or
warnings or other information. Many developers, who understand more advanced
topics, may not even know about it. The language does nothing to help with
this. It's far better to be more explicit than assuming everyone who looks at
your code understands the full ECMAScript 5 standard.

~~~
taco_emoji
It's the same reason that, yes, you can put "var x" in an if-block, but it's
bad practice because it misleads the reader (even one who _knows_ that
Javascript is function scoped) into thinking that x is block-scoped.

~~~
BinaryIdiot
I'm almost embarrassed to say it took me way to long to realize JavaScript
wasn't block scoped.

~~~
taco_emoji
Same here! It's probably the norm, honestly.

Javascript never should've had C-like syntax if it was to have the feature set
it does. Its syntax descends from a tradition of languages that have _none_ of
its actual features. Most other C-like languages have block scope[0]. So the
syntax PLUS the terrible, awful, no-good very bad name lead you to believe
it's more-or-less dynamic Java, when nothing could be further from the truth.

[0] ...and require declaration before usage, and have sensible 'this'
semantics, and are class-based, and have function parameters that are more
than just syntactic sugar, and have ACTUAL arrays, and...

------
fleitz
jQuery the useful parts.

------
yakshaving_jgt
Let’s replace non-standard JavaScript syntax-sugar with more non-standard
JavaScript syntax-sugar. Except we don’t like that the first non-standard
thing is so terse so let’s improve it with a more verbose notation. We don’t
want it to be too verbose though, so let’s drop the semicolons.

This is definitely progress. I’m quite convinced that the users of our
applications will feel the difference, and they’ll love us for it.

Wow.

------
vsaiz
funny! I had the same idea a few months ago, 1 extra feature: .off binding to
removeEventListener ;)

[https://gist.github.com/vectorsize/feda8ac1ebc889c33b6f](https://gist.github.com/vectorsize/feda8ac1ebc889c33b6f)

not as tested as yours…

