How to find node position by given node attribute?

Hi guys,

I am trying to find node position by given attribute of the node, but without success. I would be grateful for ideas/suggestions. Currently I have following function:

  findNode(node, pos, predicate) {
    if (predicate(node)) {
      return {node, pos}
    }

    for (let i = 0; i < node.childCount; i++) {
      let child = node.child(i)
      pos += child.nodeSize

      let found = this.findNode(child, pos, predicate)
      if (found) {
        return found
      }
    }

    return null
  }

Try

function findNode(node, pos, predicate) {
  let found
  node.descendants((node, pos) => {
    if (predicate(node)) found = {node, pos}
    if (found) return false
  })
  return found
}
1 Like

Thank you!

Hi,

According to the documentation the node.descendants method will call the callback for every descendant node, which is not desirable, especially when we start the search from the top. Is there a better way, let say when node is found, i want to stop iteration over other nodes.

Thank you in advance!

1 Like

Seems this implementation does not work correct, because when i have empty document and I call findNode(pmeditor.doc, 0, predicate) i get fo position 0 which is correct, but when i have document with content lets say only one Heading(actually is custom pm node created by me) I also get for position 0.

It’ll return undefined, not 0, when there’s no match.

In both cases, we have match, but in first case match is the pm.doc node in second case match is node below the pm.doc. I am talking about position of the node, not about the node itself. I think the position calculation is not correct.

Ok, @marijn seems like the function return position as node-local offset, but i need it as document-wide.

Yes, that’s exactly what that function does. It’d be nice if you could spend a bit more time looking at it before firing off more dissatisfied comments here.

Note that I left in the pos argument from your example, though that’s actually ignored. And that function will find the last node that matches. You can flip the two statements in the callback body to make it return the first instance.

And no, it won’t search the whole document after it found a match.

Hi @marijn,

I did not want to offend you! I write here because according to the documentation is not clear that descendants method of node will stop after callback function return false, also seems like i misunderstanding that pos argument given to the callback will be node-local offset not document-wide. I am looking for solution that will give me document wide position.

Again please excuse me I don’t want to offend you!

Sincerely,

Indeed, those docs weren’t very complete. Improved here.

It’s local to the node you called descendants on, which I guess would be the document.