Last active
September 13, 2025 12:13
-
Star
(1,935)
You must be signed in to star a gist -
Fork
(123)
You must be signed in to fork a gist
-
-
Save paulirish/12fb951a8b893a454b32 to your computer and use it in GitHub Desktop.
Revisions
-
paulirish revised this gist
May 26, 2025 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,8 +7,8 @@ Because you want the $ of jQuery without the jQuery. You may be interested in bling.js if you get tired of the `Array.from(document.querySelectorAll('.foo')).forEach(… ` rodeo. It does this: ```js // Array methods w/ the qSA result document.querySelectorAll('input').map(el => /* ... */); // on() rather than addEventListener() document.body.on('dblclick', evt => /* ... */); -
paulirish revised this gist
Nov 22, 2024 . 2 changed files with 35 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,15 +1,6 @@ /* bling.js */ window.$ = document.querySelector.bind(document); 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 = function(name, fn) { this.forEach((elem) => elem.on(name, fn)); }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -13,22 +13,46 @@ document.querySelectorAll('input').forEach(el => /* ... */); // on() rather than addEventListener() document.body.on('dblclick', evt => /* ... */); // classic jQuery + 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.~ * In Nov 2024 I made a breaking change (ya know, 10yrs later) where $$ is qSA and $ is qS. This matches how these [symbols are defined within DevTools Console](https://developer.chrome.com/docs/devtools/console/utilities#querySelector-function). * Bling plays well with authoring ES6 (and beyond!) * Resig explored this stuff a while ago: [github.com/jeresig/nodelist](http://github.com/jeresig/nodelist) * Bling works everywhere. #### 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. _2024 Paul here: whelp, they added iterable to NodeList but not EventTarget. seems good._ * 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. * See comments for alternatives where folks have more fleshed out editions of this. #### Typescript declaration (Added 2024..) ```ts declare global { interface Node { on(name: string, fn: EventListenerOrEventListenerObject): void; } interface Window { on(name: string, fn: EventListenerOrEventListenerObject): void; $(selector: string): Element | null; $$(selector: string): NodeListOf<Element>; } interface NodeList extends Array<Node> { on(name: string, fn: EventListenerOrEventListenerObject): void; } } ``` -
paulirish revised this gist
Jul 23, 2024 . 2 changed files with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,12 +4,12 @@ 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); }); }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,7 +4,7 @@ Because you want the $ of jQuery without the jQuery. ------------------------------------ You may be interested in bling.js if you get tired of the `Array.from(document.querySelectorAll('.foo')).forEach(… ` rodeo. It does this: ```js // forEach over the qSA result, directly. -
paulirish revised this gist
Aug 4, 2016 . 1 changed file with 1 addition and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,11 +4,7 @@ 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: ```js // forEach over the qSA result, directly. -
paulirish revised this gist
Aug 4, 2016 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,13 +12,13 @@ What bling'll do for ya: ```js // 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. -
paulirish revised this gist
Aug 4, 2016 . 1 changed file with 3 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,19 +12,13 @@ What bling'll do for ya: ```js // 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. -
paulirish revised this gist
Aug 4, 2016 . 1 changed file with 0 additions and 34 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,34 +0,0 @@ -
paulirish revised this gist
Jul 1, 2015 . 2 changed files with 6 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,15 +1,15 @@ /* 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); }); } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -41,4 +41,4 @@ It doesn't do anything else. This is **not** a jQuery equivalent. * 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](https://github.com/Flet/semistandard) for style. I tried standard sans-semicolons, but can't get used to it. -
paulirish revised this gist
Jun 15, 2015 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -27,6 +27,8 @@ $('p').on('click', function (e) { }) ``` 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. -
paulirish revised this gist
Jun 15, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,3 @@ # bling.js Because you want the $ of jQuery without the jQuery. @@ -40,3 +39,4 @@ $('p').on('click', function (e) { * 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 [standard](https://github.com/feross/standard) for style. I love semicolons too, but am giving it a go without them here. TBH, I'll probably end up on [semi-standard](https://github.com/Flet/semistandard) in the end. -
paulirish revised this gist
May 2, 2015 . 4 changed files with 59 additions and 53 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,28 +1,15 @@ /* 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) }) } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,17 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,42 @@ # bling.js Because you want the $ of jQuery without the jQuery. ------------------------------------ You could call this a microlibrary, but really it's just some code that works. You may be interested in this library if you get tired of the `[].slice.call( document.querySelectorAll('.foo'), function(){ … ` rodeo. What bling'll do for ya: ```js // forEach over the qSA result, directly. document.querySelectorAll('input').forEach(function (el) { // … }) // on() rather than addEventListener() document.body.on('dblclick', function (e) { // … }) // classic $ + on() $('p').on('click', function (e) { // … }) ``` #### 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](http://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. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,3 @@ /* npm install -g browser-repl cat bling.js test.js | uglifyjs | pbcopy # copy bling & tests to clipboard @@ -7,34 +6,29 @@ # paste and zoooom! */ var input1 = document.createElement('input') input1.id = 'one' document.body.appendChild(input1) var input2 = document.createElement('input') input2.id = 'two' document.body.appendChild(input2) $('input').on('click', function (e) { console.log('PASS!', e.target.id, ' clicked! ') }) window.on('click', function (e) { console.log('Pass! window received click too!') }) // either click 'em or this is for testing… function simulateClick (elem) { var evt = document.createEvent('MouseEvents') evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) var canceled = !elem.dispatchEvent(evt) } simulateClick(input1) setTimeout(function () { simulateClick(input2) }, 500) -
paulirish revised this gist
May 2, 2015 . 2 changed files with 16 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,10 +2,9 @@ // the kind of thing you toss into the page as you start prototyping window.$ = document.querySelectorAll.bind(document) Node.prototype.on = window.on = function (name, fn) { this.addEventListener(name, fn) } @@ -17,12 +16,13 @@ NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn this.forEach(function (elem, i) { elem.on(name, fn) }) } // Notes: // it's all resig's fault. github.com/jeresig/nodelist // setting `Node.prototype.on = EventTarget.prototype.addEventListener` would be sweet but, no funciona in IE/Saf // not done: dispatchEvent & removeEventListener shortcuts, but who caaares // doesn't work on Android 2.3 or iOS 5.0. Works everywhere else including IE8. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,9 +1,11 @@ /* npm install -g browser-repl cat bling.js test.js | uglifyjs | pbcopy # copy bling & tests to clipboard repl # see list of browsers to try it in repl ie # paste and zoooom! */ var input1 = document.createElement('input'); input1.id = 'one'; @@ -17,7 +19,9 @@ document.body.appendChild(input2); $('input').on('click', function(e) { console.log('PASS!', e.target.id, ' clicked! '); }) window.on('click', function(e){ console.log('Pass! window received click too!') }); @@ -33,4 +37,4 @@ function simulateClick(elem) { simulateClick(input1) setTimeout(function(){ simulateClick(input2) }, 500); -
paulirish revised this gist
Apr 30, 2015 . 1 changed file with 8 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,15 +1,13 @@ // bling // the kind of thing you toss into the page as you start prototyping Window.prototype.$ = document.querySelectorAll.bind(document) Node.prototype.on = Window.prototype.on = function (name, fn) { this.addEventListener(name, fn) } // NodeList needs all Array goodies NodeList.prototype.__proto__ = Array.prototype @@ -19,7 +17,12 @@ NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn this.forEach(function (elem, i) { elem.on(name, fn) }) } // // Notes: // it's all resig's fault. github.com/jeresig/nodelist // setting `Node.prototype.on = EventTarget.prototype.addEventListener` would be sweet but, no funciona in IE/Saf // not done: dispatchEvent & removeEventListener shortcuts, but who caaares -
paulirish revised this gist
Apr 30, 2015 . 3 changed files with 44 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -9,6 +9,7 @@ Window.prototype.$ = document.querySelectorAll.bind(document) Node.prototype.on = function (name, fn) { this.addEventListener(name, fn) } // setting to EventTarget.prototype.addEventListener; directly would be nice, but not supported everywhere. // NodeList needs all Array goodies NodeList.prototype.__proto__ = Array.prototype @@ -19,3 +20,6 @@ NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn elem.on(name, fn) }) } // todo: dispatchEvent & removeEventListener This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,5 +10,8 @@ document.body.on('dblclick', function (e) { // classic Bling + on() $('p').on('click', function (e) { e.currentTarget.hidden = true }) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,36 @@ function simulateClick(elem) { var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); var canceled = !elem.dispatchEvent(evt); } var input1 = document.createElement('input'); input1.id = 'one'; document.body.appendChild(input1); var input2 = document.createElement('input'); input2.id = 'two'; document.body.appendChild(input2); $('input').on('click', function(e) { console.log('PASS!', e.target.id, ' clicked! '); }) // either click 'em or this is for testing… function simulateClick(elem) { var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); var canceled = !elem.dispatchEvent(evt); } simulateClick(input1) setTimeout(function(){ simulateClick(input2) }, 500); -
paulirish revised this gist
Apr 8, 2015 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,8 @@ // bling // the kind of thing you toss into the page as you start prototyping // also a prollyfill. // it's all resig's fault. github.com/jeresig/nodelist Window.prototype.$ = document.querySelectorAll.bind(document) -
paulirish revised this gist
Apr 8, 2015 . 2 changed files with 14 additions and 18 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,17 +1,17 @@ // blinggggggggggg Window.prototype.$ = document.querySelectorAll.bind(document) Node.prototype.on = function (name, fn) { this.addEventListener(name, fn) } // NodeList needs all Array goodies NodeList.prototype.__proto__ = Array.prototype // NodeList needs EventTarget goodies but iterated NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn) { this.forEach(function (elem, i) { elem.on(name, fn) }) } // todo: dispatchEvent & removeEventListener This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,18 +1,14 @@ // We should be able to forEach on the qSA result. document.querySelectorAll('input').forEach(function (el) { el.readOnly = true }) // addEventListhistakestoolongtotype. on() method document.body.on('dblclick', function (e) { console.log('double clicked the body') }) // classic Bling + on() $('p').on('click', function (e) { p.hidden = true }) -
paulirish created this gist
Apr 8, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,17 @@ // blinggggggggggg Window.prototype.$ = document.querySelectorAll.bind(document); Node.prototype.on = function (name, fn) { this.addEventListener(name, fn); } // NodeList needs all Array goodies NodeList.prototype.__proto__ = Array.prototype; // NodeList needs EventTarget goodies but iterated NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn) { this.forEach(function(elem, i) { elem.on(name, fn); }); }; // todo: dispatchEvent & removeEventListener This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,18 @@ // We should be able to forEach on the qSA result. document.querySelectorAll('input').forEach(function(el){ el.readOnly = true }) // addEventListhistakestoolongtotype. on() method document.body.on('dblclick', function(e){ console.log('double clicked the body'); }) // classic Bling + on() $('p').on('click', function(e){ p.hidden = true; });