Detect inline nodes click only (ignore block parent)

Hey there,

I’m trying to detect clicks on inline nodes that have a specific mark, and get the data-id attribute from them

     handleClickOn: (view, pos, node, nodePos, event, direct) => {
            if (
              node.marks.some(
                (mark) => mark.type === view.state.schema.marks.customMark
              )
            ) {
                let markId: number | undefined = node.marks.find(
                (mark) => mark.type === view.state.schema.marks.customMark
              )?.attrs.markId;
              if (markId) {
                ... do stuffs
              }
            }
          },

But the problem is the node detected on click is always the parent (block node) Is there a way to only detect the most nested node that has the mark?

Looping through the descendants of the block doesn’t work here, since a block can contain multiple inline nodes with the custom mark and different IDs

node should hold the inline node the first time this is called. It will then, if the handler doesn’t return true for that, continue to be called for parent nodes. I just verified this works correctly for images. If you can confirm that it’s not working for you, please show what kind of node you are clicking.

Hey @marijn

I’ve tried different configurations, but the problem persists

This is the content I’m using:

<p>This <custom-mark data-id=’1’>doesn’t work</custom-mark> as <custom-mark data-id=’2’>intented</custom-mark></p>

 <ul> 

<li> That’s a bullet list with one … </li> 

<li> … or two list items. </li> 

</ul>

 <p> Here is a nice image I’ve found online: </p> 

<img src="https://source.unsplash.com/8xznAGy4HcY/800x400" />

<p>ProseMirror is very cool!</p>

When logging the node in handleClickOn (outside the condition) and clicking the “intended” work in the editor, I get the parent block node (paragraph) and not the inline one:

{
  "type": "paragraph",
  "content": [
    {
      "type": "text",
      "text": "This"
    },
    {
      "type": "text",
      "marks": [
        {
          "type": "customMark",
          "attrs": {
            "markId": 84
          }
        }
      ],
      "text": "doesn't work"
    },
    {
      "type": "text",
      "text": "as"
    },
    {
      "type": "text",
      "marks": [
        {
          "type": "customMark",
          "attrs": {
            "markId": 85
          }
        }
      ],
      "text": "intended"
    }
  ]
}

The function is called only once because I don’t return true

Marks are not nodes, and as such they indeed aren’t included in the calls for handleClickOn.

As simple as this, I feel dumb, thanks @marijn

Taking the opportunity to ask a follow-up question:

Is there a reliable way to detect which mark is clicked on? Knowing that a node can contain multiple marks (like in my example)

You could use handleClick, resolve the position that was clicked, and use ResolvedPos.marks() to get the set of marks active at that position.

It works!

Thanks a lot @marijn