Skip to content

Instantly share code, notes, and snippets.

@MadeByMike
Forked from paulirish/bling.js
Last active July 23, 2021 12:32
Show Gist options
  • Save MadeByMike/7e7707eff116229a5948 to your computer and use it in GitHub Desktop.
Save MadeByMike/7e7707eff116229a5948 to your computer and use it in GitHub Desktop.

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:

// 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) {
  // …
})

// delegate events
$('p').on('click', '.delegate', 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
  • 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.
/* bling.js */
window.$ = document.querySelectorAll.bind(document)
Node.prototype.on = window.on = function (name, delegate, fn) {
var f
var target = this, match = false
var matches = this.matchesSelector || this.mozMatchesSelector || this.webkitMatchesSelector || this.oMatchesSelector || (function (name) {
$(name).forEach(function (elm) {
if (elm === target){
match = true
}
});
return match
});
if (typeof delegate === 'function') {
f = delegate
} else {
f = function(e){
if (matches.call(e.target, delegate)) {
fn.call(e.target, e)
}
}
}
this.addEventListener(name, f)
}
NodeList.prototype.__proto__ = Array.prototype;
NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, delegate, fn) {
this.forEach(function (elem, i) {
elem.on(name, delegate, fn)
});
}
/*
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'
document.body.appendChild(input1)
var input2 = document.createElement('input')
input2.id = 'two'
document.body.appendChild(input2)
var container1 = document.createElement('div')
container1.id = 'container'
var child1 = document.createElement('input')
child1.id = 'delegate'
container1.appendChild(child1)
document.body.appendChild(container1)
$('input').on('click', function (e) {
console.log('PASS!', e.target.id, ' clicked! ')
})
window.on('click', function (e) {
console.log('Pass! window received click too!')
})
$('#container').on('click', '#delegate', function (e) {
console.log('PASS! delegate event works!', 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)
setTimeout(function () { simulateClick(child1) }, 1000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment