Skip to content

Instantly share code, notes, and snippets.

@kaspermeyer
Created December 13, 2018 14:06
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kaspermeyer/7fe28bb7c55c2810e7b5f3d5e67c1a44 to your computer and use it in GitHub Desktop.
Save kaspermeyer/7fe28bb7c55c2810e7b5f3d5e67c1a44 to your computer and use it in GitHub Desktop.
Dispatch jQuery events as regular DOM events
# ~ Dispatch jQuery events as regular DOM events ~
#
# Delegated events are given a new name in the format `jquery:<original event name>`.
# If you delegate `ajax:send` you will be able to listen for `jquery:ajax:send`
# on native event listeners such as Stimulus actions and `EventTarget.addEventListener`.
#
# Notes:
# * The first parameter must be called "event".
# * The parameters can be accessed as members on the `event.detail` object.
#
# Example:
# delegate 'ajax:send', parameters: ['event', 'xhr']
# document.addEventListener 'jquery:ajax:send', (event) -> console.log(event.detail)
#
delegate = (eventName, {parameters}) ->
handler = (args...) ->
data = {}
data[name] = args[index] for name, index in parameters
delegatedEvent = new CustomEvent("jquery:#{eventName}",
bubbles: true,
cancelable: true,
detail: data)
data.event.target.dispatchEvent(delegatedEvent)
$(document).on(eventName, handler)
@kaspermeyer
Copy link
Author

# jQuery UJS
#
# Source: https://github.com/rails/jquery-ujs/wiki/ajax
#
delegate 'ajax:before',           parameters: ['event']
delegate 'ajax:beforeSend',       parameters: ['event', 'xhr', 'settings']
delegate 'ajax:send',             parameters: ['event', 'xhr']
delegate 'ajax:success',          parameters: ['event', 'data', 'status', 'xhr']
delegate 'ajax:error',            parameters: ['event', 'xhr', 'status', 'error']
delegate 'ajax:complete',         parameters: ['event', 'xhr', 'status']
delegate 'ajax:aborted:required', parameters: ['event', 'elements']
delegate 'ajax:aborted:file',     parameters: ['event', 'elements']

@kaspermeyer
Copy link
Author

kaspermeyer commented Dec 13, 2018

# Select 2 (v4.0)
#
# Source: https://select2.org/programmatic-control/events
#
delegate 'select2:closing',     parameters: ['event']
delegate 'select2:close',       parameters: ['event']
delegate 'select2:opening',     parameters: ['event']
delegate 'select2:open',        parameters: ['event']
delegate 'select2:selecting',   parameters: ['event']
delegate 'select2:select',      parameters: ['event']
delegate 'select2:unselecting', parameters: ['event']
delegate 'select2:unselect',    parameters: ['event']

@kaspermeyer
Copy link
Author

# Bootstrap (v4.1)
#
# Source: https://getbootstrap.com/docs/4.1/getting-started/javascript/#events
#
# ~ alert
delegate 'close.bs.alert',        parameters: ['event']
delegate 'closed.bs.alert',       parameters: ['event']
# ~ carousel
delegate 'slide.bs.carousel',     parameters: ['event']
delegate 'slid.bs.carousel',      parameters: ['event']
# ~ collapse
delegate 'show.bs.collapse',      parameters: ['event']
delegate 'shown.bs.collapse',     parameters: ['event']
delegate 'hide.bs.collapse',      parameters: ['event']
delegate 'hidden.bs.collapse',    parameters: ['event']
# ~ dropdown
delegate 'show.bs.dropdown',      parameters: ['event']
delegate 'shown.bs.dropdown',     parameters: ['event']
delegate 'hide.bs.dropdown',      parameters: ['event']
delegate 'hidden.bs.dropdown',    parameters: ['event']
# ~ tab
delegate 'show.bs.tab',           parameters: ['event']
delegate 'shown.bs.tab',          parameters: ['event']
delegate 'hide.bs.tab',           parameters: ['event']
delegate 'hidden.bs.tab',         parameters: ['event']
# ~ modal
delegate 'show.bs.modal',         parameters: ['event']
delegate 'shown.bs.modal',        parameters: ['event']
delegate 'hide.bs.modal',         parameters: ['event']
delegate 'hidden.bs.modal',       parameters: ['event']
# ~ popover
delegate 'show.bs.popover',       parameters: ['event']
delegate 'shown.bs.popover',      parameters: ['event']
delegate 'hide.bs.popover',       parameters: ['event']
delegate 'hidden.bs.popover',     parameters: ['event']
delegate 'inserted.bs.popover',   parameters: ['event']
# ~ scrollspy
delegate 'activate.bs.scrollspy', parameters: ['event']
# ~ tooltip
delegate 'show.bs.tooltip',       parameters: ['event']
delegate 'shown.bs.tooltip',      parameters: ['event']
delegate 'hide.bs.tooltip',       parameters: ['event']
delegate 'hidden.bs.tooltip',     parameters: ['event']
delegate 'inserted.bs.tooltip',   parameters: ['event']

@asecondwill
Copy link

Works for Zurb Foundation too.

delegate 'moved.zf.slider', parameters: ['event']

And then
<div class="slider visits-slider" data-action="jquery:moved.zf.slider->provision#update">

@asecondwill
Copy link

asecondwill commented Apr 2, 2019

This actually gives an errorJust noticed this doesn't work for ie11

Object doesn't support this action
Line 16 of the JS(converted from coffee)

delegatedEvent = new CustomEvent("jquery:" + eventName, {

original coffee:
delegatedEvent = new CustomEvent("jquery:#{eventName}",

@asecondwill
Copy link

CustomEvent isn't supported in ie11, but there is a polyfil which worked great for me:

https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent


(function () {

  if ( typeof window.CustomEvent === "function" ) return false;

  function CustomEvent ( event, params ) {
    params = params || { bubbles: false, cancelable: false, detail: null };
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;
   }

  CustomEvent.prototype = window.Event.prototype;

  window.CustomEvent = CustomEvent;
})();

@n4cr
Copy link

n4cr commented Aug 13, 2020

This is a noob question but how should I use this coffee script? I have my project fully setup with backend django and stimulusjs with webpack. I don't get where I can include this delegator.

Thanks in advance

@kaspermeyer
Copy link
Author

kaspermeyer commented Aug 13, 2020

@n4cr Anywhere in your setup should be good. Make sure you have a CoffeeScript loader enabled in your webpack configuration.

@n4cr
Copy link

n4cr commented Aug 13, 2020

Thanks Kasper for the answer.

@n4cr
Copy link

n4cr commented Aug 13, 2020

In case someone needs this in JS:

const delegate = function (eventName, parameters) {
  const handler = (...args) => {
    const data = {}
    parameters.forEach((name, i) => data[name] = args[i]);
    const delegatedEvent = new CustomEvent("jquery:" + eventName, {
        bubbles: true,
        cancelable: true,
        detail: data
      }
    )
    data.event.target.dispatchEvent(delegatedEvent)
    console.log(delegatedEvent);
  }
  $(document).on(eventName, handler)
};

@leastbad
Copy link

leastbad commented Sep 7, 2020

I wish I'd seen this thread a long time ago!

I ended up creating jquery-events-to-dom-events to handle this problem in a way that would drop right into Stimulus controllers.

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