Inserting event listener into HTML tag programatically

I am trying to insert an event listener into an HTML tag programatically.

I have a span tag like <span>Value</span>, and I want to take Value and do some stuff with it when I click the span element.

I imagine it would look something like:
<span onclick={function where I do stuff with Value}>Value</span>

I have tried to follow along the notebook on hypertext literals but can’t seem to make this work.

So I created a simple notebook with a sample problem. Any help with this would be appreciated, I still am trying to get my head around hypertext literals/inserting HTML etc!

This is my notebook:

1 Like

hows this? Event listener on span tag that updates value / Toph Tucker / Observable

1 Like

Thanks for your reply, the target.innerHTML part is certainly helpful.

But I think the main problem that I’m struggling with (sorry if it wasn’t evident in the way I phrased the question) is inserting the onclick= part programatically. I want to start off with

<span>Value</span> ← (I get given this as a string)

and end up with

<span onclick={function where I do stuff with Value}>Value</span>

and display that as HTML. Using a regex to add the onclick part does weird things. Hope that is clearer.

I’ve tried playing around with this problem - here’s my latest attempt.

I think you might do this much more cleanly by d3.selecting the html literal and programmatically adding the event listener. Here’s an example:

If you open the notebook (by clicking on its name in the iframe footer), you should notice the following:

  • The text of the html literal is defined by a string in a separate cell,
  • the function f that converts from decimal to binary is also defined in a separate cell, and
  • the event is set using, as mentioned above.

As a side note, a friend of mine met Douglas Adams at a book signing and asked him to write the number 42 in the book he was signing. When my friend got his book back, 42 was written as 101010.

1 Like

I agree with @mcmcclur; I would avoid trying to do this by manipulating HTML source (strings) and instead do it using the DOM API (possibly using a helper library, such as D3). For example, you could have a function that adds event listeners to a given element:

function withClick(element) {
  element.addEventListener("click", () => doStuff());
  return element;

And then apply your listeners to an element in another cell like so:

withClick(htl.html`<span>click me</span>`)

Another approach would be to wrap the elements (which is used exactly the same way as above):

function withClick(children) {
  return htl.html`<span onclick=${() => doStuff()}>${children}</span>`;

Using the DOM will be a lot easier than trying to parse and rewrite HTML source yourself (and you can’t generally serialize event listeners anyway).

1 Like

Thank you @tophtucker @mcmcclur and @mbostock for all the good advice, I managed to use d3 to achieve what I wanted. Can’t believe I struggled for a week to do something so simple! Ah well got there in the end. :slight_smile:

1 Like