Skip to content

Instantly share code, notes, and snippets.

@paulirish
Last active February 20, 2024 14:11
Show Gist options
  • Save paulirish/12fb951a8b893a454b32 to your computer and use it in GitHub Desktop.
Save paulirish/12fb951a8b893a454b32 to your computer and use it in GitHub Desktop.
bling dot js

bling.js

Because you want the $ of jQuery without the jQuery.


You may be interested in bling.js if you get tired of the [].slice.call( 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.

Notes:

  • 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: github.com/jeresig/nodelist
  • 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);
});
}
@gugadev
Copy link

gugadev commented Oct 10, 2016

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

@o0101
Copy link

o0101 commented Nov 17, 2016

Inspired by this to make a version here https://github.com/dosaygo-coder-0/postjs/blob/master/postbling/src/postbling.js

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

@skylarmb
Copy link

skylarmb commented Mar 1, 2017

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

@GaurangTandon
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 - http://stackoverflow.com/questions/42825990/extending-prototype-of-dom-elements-inside-iframes
Any ideas anyone?

@Ollie-w
Copy link

Ollie-w commented Jun 5, 2017

Is this safe to use in production?

@paulirish
Copy link
Author

@Ollie-w yeah totally.

@argyleink
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

https://github.com/argyleink/blingblingjs

@paulirish
Copy link
Author

@AdaRoseCannon has a nice extension of this idea which maps ALL things in the Element prototype onto the NodeList prototype https://gist.github.com/AdaRoseCannon/d95a7cbb8edd730443c62f0daff875ac

@nuxodin
Copy link

nuxodin commented Nov 16, 2020

Similiar:
https://github.com/nuxodin/domProxy
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