Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to register alternate events? #56

Closed
drnic opened this issue Dec 17, 2022 · 9 comments · Fixed by #74
Closed

How to register alternate events? #56

drnic opened this issue Dec 17, 2022 · 9 comments · Fixed by #74
Assignees
Labels
bug Something isn't working

Comments

@drnic
Copy link
Contributor

drnic commented Dec 17, 2022

In https://github.com/hopsoft/turbo_reflex/blob/main/README.md#reflex-triggers it suggests we can override default events with TurboReflex.registerEvent but this method doesn't exist for me.

I found TurboReflex.registerEventDelegate but I couldn't get it to register onmouseover or some other event types.

TurboReflex.registerEventDelegate('onmouseover', ['p[data-turbo-reflex]'])

Similarly, I tried inline custom events like data-turbo-reflex="onmouseover->CounterReflex#increment" but didn't see the reflex action trigger.

@hopsoft
Copy link
Owner

hopsoft commented Dec 18, 2022

You'll want to remove the on prefix in the event name. Here's an example.

TurboReflex.registerEventDelegate('mouseover', ['p[data-turbo-reflex]'])

TurboReflex 2022-12-18 05-50-23

Let me know if this works for you.

@hopsoft
Copy link
Owner

hopsoft commented Dec 28, 2022

Note that after the lib rebrand to TurboBoost Commands, this code should be changed to:

TurboBoost.Commands.registerEventDelegate(...)

@adamjleonard
Copy link

@hopsoft I wanted to follow up on this conversation. I've attempted to register a keyup, keydown and keypress event but unfortunately it didn't trigger the command.

I unfortunately don't have a sample project for you at the moment and I'll see if I can take this local and do some debugging myself, but just wanted to put it on your radar.

@hopsoft
Copy link
Owner

hopsoft commented Jan 7, 2023

Interesting. If it helps, this is where/how the library registers the default event delegates. https://github.com/hopsoft/turbo_boost-commands/blob/main/app/javascript/index.js#L92-L98

And here's where the library identifies a match when the event is triggered.

function isRegisteredForElement (eventName, element) {

@hopsoft
Copy link
Owner

hopsoft commented Jan 17, 2023

Verified that we definitely have a bug related to registering additional events. The click handler is taking precedence. Will dive into this shortly.

@hopsoft hopsoft added the bug Something isn't working label Jan 17, 2023
@hopsoft hopsoft self-assigned this Jan 18, 2023
@adamjleonard
Copy link

adamjleonard commented Jan 18, 2023

I tested this current branch against keyup as well and that seems to still fail. I hope tomorrow to actually sit down and take a look at debugging.

EDIT

I was able to get this to work if I did the following

TurboBoost.Commands.registerEventDelegate("change", []);
TurboBoost.Commands.registerEventDelegate("click", []);

TurboBoost.Commands.registerEventDelegate("keydown", [
  "input[data-turbo-command]",
]);

but unfortunately this prevented any actual value being typed in to the input

@adamjleonard
Copy link

Excuse my stupidity but is there a specific reason to not use something similar to stimulus where you can bind the action with change->Command->method

@hopsoft
Copy link
Owner

hopsoft commented Jan 18, 2023

Great question. Yes, there is a reason we opt for event delegation over per-element bound event listeners. Low level tools and libraries (like this one) can't make too many assumptions about the JavaScript ecosystem they're running within.

One example to illustrate the challenges is related to how StimulusReflex implicitly registers a StimulusJS controller for events that declare a data attribute that haven't already registered a StimulusJS controller with similar behavior. Detecting this is problematic because there's no way for the library to know how the JavaScript assets are organized or how they'll be loaded and parsed for a given application. This scenario is exacerbated with new techniques like import maps etc... Any client side Stimulus controller that's implicitly wired up can introduce unintentional and unwanted duplicate behavior (i.e. trigger RPC calls multiple times from a single client side event).

Event delegation eliminates this problem entirely, so it doesn't matter how the JavaScript assets are resolved, loaded, and parsed on the client. The primary caveat of delegation being that it limits us to bubbling events.

  • abort
  • blur
  • change
  • click
  • contextmenu
  • dblclick
  • error
  • focus
  • input
  • keydown
  • keypress
  • keyup
  • load
  • mousedown
  • mousemove
  • mouseout
  • mouseover
  • mouseup
  • mousewheel
  • resize
  • scroll
  • select
  • submit
  • unload

Having said that, event delegation also works with custom events and each registered delegate can include multiple selectors per event. Selectors for each delegate can be as simple or as sophisticated as desired.


In your example above, I would expect the following delegate to work.

const existingChangeDelegate = TurboBoost.Commands.eventDelegates.find(e => e.name === 'change')
TurboBoost.Commands.registerEventDelegate('change', [...existingChangeDelegate.selectors, '.my-element[data-turbo-command]'])

I could probably make this a bit more intuitive though.

@hopsoft
Copy link
Owner

hopsoft commented Jan 18, 2023

Just created ticket #75 to help with event delegate overrides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants