Skip to content

Instantly share code, notes, and snippets.

Last active February 20, 2024 14:11
Star You must be signed in to star a gist
Save paulirish/12fb951a8b893a454b32 to your computer and use it in GitHub Desktop.
bling dot js


Because you want the $ of jQuery without the jQuery.

You may be interested in bling.js if you get tired of the [] document.querySelectorAll('.foo'), function(){ … rodeo. It does this:

// forEach over the qSA result, directly.
document.querySelectorAll('input').forEach(el => /* ... */);

// on() rather than addEventListener()
document.body.on('dblclick', evt => /* ... */);

// classic $ + on()
$('p').on('click', el => /* ... */);

It doesn't do anything else. This is not a jQuery equivalent.


  • on() works on elements, document, window, and results from querySelector & querySelectorAll.
  • $ is qSA so if you're grabbing a single element you'll have to [0] it.
  • Bling plays well with authoring ES6
  • Resig explored this stuff a while ago:
  • Bling doesn't work on Android 2.3 or iOS 5.0. Works everywhere else including IE8 (assuming Function.bind)

Nerdy implementation notes:

  • The NodeList prototype usually inherits from Object, so we move it to Array.
  • I'm curious how ES6/7 would let a NodeList be iterable and inherit from EventTarget
  • Setting Node.prototype.on = EventTarget.prototype.addEventListener is awesome. It works in Chrome/FF but not yet in IE/Safari.
  • I haven't set up any off() or trigger() to map to dispatchEvent & removeEventListener. I'm OK with that.
  • I'm using semi-standard for style. I tried standard sans-semicolons, but can't get used to it.
/* bling.js */
window.$ = document.querySelectorAll.bind(document);
Node.prototype.on = window.on = function (name, fn) {
this.addEventListener(name, fn);
NodeList.prototype.__proto__ = Array.prototype;
NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn) {
this.forEach(function (elem, i) {
elem.on(name, fn);
Copy link

Doing this is somewhat a bad practice:

NodeList.prototype.__proto__ = Array.prototype;

NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn) {
  this.forEach(function (elem, i) {
    elem.on(name, fn);

Don't mess with the native prototypes!

Why don't you try it this way?

window.$ = document.querySelectorAll.bind(document);

Node.prototype.on = window.on = Node.prototype.addEventListener;

NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn) { {
         elem.addEventListener(name, fn, false);

Copy link

What about changing the prototype of HTMLCollection as well so they are easier to iterate over? You can find HTMLCollection's in properties like ParentNode.children

Not sure of the side effects, yet.

HTMLCollection.prototype.__proto__ = Array.prototype;

Copy link

put code in github repo -
to make it open & conveninent for contribution

Copy link

gugadev commented Oct 10, 2016

Better $ to querySelector and $$ to querySelectorAll instead of $('.something')[0].on(...).

Copy link

o0101 commented Nov 17, 2016

Inspired by this to make a version here

What's new?

  • on applies to EventTargets and Arrays containing them, so you can do this:
$('*').slice(3).on('click', reveal );
$`div`.on( 'touchstart', dragOn ).on( 'touchend', dragOff );
  • NodeList and HTMLCollection both now delegate to Array
  • the on functions return this to allow chaining
  • and made it more ES5/6/7-y including Object.setPrototypeOf

These included ideas from @MadLittleMods and @spiralx and @joa

Copy link

skylarmb commented Mar 1, 2017

@bjankord awesome. thanks for the tip. Sadly some of us do have to support IE9... 🎉

Copy link

This does NOT work for DOM elements inside iframes. Here's the related SO question with a related code sample - based on the same principles as above code - with a reproducible example -
Any ideas anyone?

Copy link

Ollie-w commented Jun 5, 2017

Is this safe to use in production?

Copy link

@Ollie-w yeah totally.

Copy link

argyleink commented Apr 1, 2018

I think I have an interesting fork:

  • only mutates the nodes queried with the exported function
  • offers 'off'
  • offers nice attribute CRUD operations

Copy link

@AdaRoseCannon has a nice extension of this idea which maps ALL things in the Element prototype onto the NodeList prototype

Copy link

nuxodin commented Nov 16, 2020

A (proxied) Nodelist with all Apis of Elements (also future).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment