How to walk ancestor DOM nodes on a click event

Background

I want to track analytic events when people click on <a> tags in our app. e.g. {name="Clicked on X", data = {....}}. These go Segment via a JS port.

We have a tags with href which trigger navigation event via Browser.application.

My first attempt was to put onClick handlers in the <a> tags. But that didn’t work because when you navigate, the current page gets unloaded, and the update for that page is never called. The app is organised using a few levels of nested updates, we only send messages to the current loaded page.

After a few other failed ideas I decided to try event delegation.

Current problem

We have a data attribute in the links e.g. `<a data-event="{name='Something"}"

Then we have a listener at the root of the app for clicks, this listener uses a decoder that looks for the presence of data-event. If it is there, then I trigger a message to track the event. This works great when you click on the DOM node that has the data-event.

If I have children DOM elements the decoder doesn’t work e.g.

<a data-event=""><span>Click here<span></a>

As data-event is not in the current target of the event the decoder fails. I need to walk the DOM up somehow looking for data.

Here is an example app https://ellie-app.com/4DKMxGw4mT3a1

The part that escapes me is how to find data-event in the target or any of the ancestor nodes.
Any help on how to do this would be great.

Thanks

You should be able to use a custom target decoder to get the data attribute. Something like this: https://ellie-app.com/4DNkXGHsGb8a1

Doesn’t elm-dom package do what you want?

Couldn’t you use Browser.Navigation to intercept the clicked links and despatch whatever port events you wanted before then following them using Browser.Navigation.load?

1 Like

I didn’t know about this package and functions like target and parentElement. I might try to use these for what I want, let’s see.

Yes thanks, this is what I’m doing. But I need to search ancestors for that data-event. E.g. you have a link with a span, when you click the span is the target, but the data in in the a. I can’t assume that the data is in the parentNode.

We do this for tracking page views. It works well.
But for other cases when we have a lot of tracking data, I would need to pass the tracking data somehow. The only way I can thing of is to put that in the url query string so it is available for sending to the tracking service. I rather avoid that.

My bad, overlooked that part of the question. I’d also be interested to know how to recursively traverse up the tree till the attribute is found.

If I understand your requirements correctly, you can do something like this. That example uses the “focusout” event, but assuming that your event provides similar data, it should work for you.

@klazuka thanks for the link, I was hoping to do something similar myself. Have updated the example with a working implementation - https://ellie-app.com/4F9XJCQXsSpa1

Learnt something today :slight_smile:

Awesome, based on those two examples I was able to figure out how to do what I wanted. https://ellie-app.com/4FbHBN493gha1
Thanks.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.