Skip to content

Instantly share code, notes, and snippets.

@octopitus
Last active February 27, 2016 09:30
Show Gist options
  • Save octopitus/758e9f16cbcee32443bc to your computer and use it in GitHub Desktop.
Save octopitus/758e9f16cbcee32443bc to your computer and use it in GitHub Desktop.
DOM event listener made easy (Writen in ES2015)

Example

Let's say that we have a #container like this

<div id="container">
  <div class="foo">Foo</div>
  <div class="bar">Bar</div>
  <div class="baz">Baz</div>
</div>

And somewhere in your app

import { handleEvent, handleEventOnce, triggerEvent } from 'dom.js'

const element = document.getElementById('container')

// Anytime you need
const handleClick = handleEvent('click', {
  onElement: element,
  matchSelector: '.foo',
  withCallback: (event, target) => {
    // Only get called when click on '.foo'.
    // Good for event delegation.
    console.log('Clicked on', target)
  }
})

// Anytime you want to remove it 
handleClick.destroy()

handleEventOnce do the same work as handleEvent. But get called only one time. So you don't need to call destroy.

function match (element, selector) {
const html = document.documentElement
const matchesSelector = html.matchesSelector || html.webkitMatchesSelector || html.msMatchesSelector || html.mozMatchesSelector
return matchesSelector.call(element, selector)
}
function elementMatchesSelector (element, selector) {
if (element && element.nodeType === 1) {
return match(element, selector)
}
}
function findClosestElementFromNode (node, {matchingSelector} = {}) {
while (node && node.nodeType !== Node.ELEMENT_NODE) {
node = node.parentNode
}
if (matchingSelector) {
while (node) {
if (elementMatchesSelector(node, matchingSelector)) {
return node
}
node = node.parentNode
}
}
return node
}
export function handleEvent (eventName, {onElement, matchingSelector, withCallback, inPhase, preventDefault, times} = {}) {
const element = onElement || document.documentElement
const selector = matchingSelector
const useCapture = inPhase === 'capturing'
function handler (event) {
if (times && --times === 0) {
handler.destroy()
}
const target = findClosestElementFromNode(event.target, {
matchingSelector: selector
})
if (target) {
if (withCallback) {
withCallback.call(target, event, target)
}
if (preventDefault) {
return event.preventDefault()
}
}
}
handler.destroy = function () {
return element.removeEventListener(eventName, handler, useCapture)
}
element.addEventListener(eventName, handler, useCapture)
return handler
}
export function handleEventOnce (eventName, options = {}) {
options.times = 1
return handleEvent(eventName, options)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment