# Approaches for finding the position of nodes

**URL:** <https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333>\
**Category:** Uncategorized\
**Created:** [December 7, 2020, 4:28pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333 "2020-12-07T16:28:08Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pier](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/pier/32/616_2.png) [@Pier](https://discuss.prosemirror.net/u/Pier)\
**Post date:** [December 7, 2020, 4:28pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/1 "2020-12-07T16:28:08Z")

</div>

I’d like to initiate a thread for discussing the best way(s) of finding the position of a node.

For empty selections what I’ve been doing is iterating the children of a parent node (or the document) and using `node.eq()` to determine if the current children is the node I’m looking for. Something like this:

```auto
function getNodePositions (node, parentNode) {
    let start, end;
    parentNode.forEach((childNode, pos) => {
        if (childNode.eq(node)) {
            start = pos;
            end = pos + node.nodeSize;
        }
    });

    return {start, end};
}

```

Usually the parent node is the document, or I just find the parent at the depth I’m interested in.

This seems to work so far, but then I remember that @marijn has insisted frequently that nodes are value types and could be duplicated in the document. I wonder if using `node.eq()` is the right approach?

For regular selections I simply use `state.doc.nodesBetween()` which doesn’t have the equality issue I mentioned earlier.

I also found [this thread](https://discuss.prosemirror.net/t/replace-a-node-using-tr-replacewith-how-to-find-node-position/388) which discusses using HTML attributes to tag DOM elements and then using `posFromDOM` but when searching the docs the method doesn’t seem to exist anymore.

So how do you do it?

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [December 7, 2020, 4:51pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/2 "2020-12-07T16:51:32Z")

</div>

The recommended approach is to not use nodes like this. If you want to remember something about something in the document, remember its position. If you need to track that across changes, map the position through the changes.

---

<div class="post-metadata">

**Author:** ![Pier](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/pier/32/616_2.png) [@Pier](https://discuss.prosemirror.net/u/Pier)\
**Post date:** [December 7, 2020, 5:32pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/3 "2020-12-07T17:32:38Z")

</div>

Thanks for your answer Marijn.

> [@marijn](#):
>
> If you want to remember something about something in the document, remember its position.

This makes sense, but the fundamental problem I face is finding the position of something in the first place to be able to use it for transforms or track it across changes.

For example, say I want to delete `$cursor.parent` with `tr.deleteRange` or `tr.delete`. I can find the start position for the transform by using `$cursor.parentOffset` but would it be ok to use `node.nodeSize` to find the end point?

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [December 7, 2020, 8:34pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/4 "2020-12-07T20:34:01Z")

</div>

> but would it be ok to use node.nodeSize to find the end point?

Absolutely.

---

<div class="post-metadata">

**Author:** ![Pier](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/pier/32/616_2.png) [@Pier](https://discuss.prosemirror.net/u/Pier)\
**Post date:** [December 9, 2020, 10:23pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/5 "2020-12-09T22:23:09Z")

</div>

After numerous attempts I think I’m **finally** getting the hang of this.

For example, to get the start/end positions of the previous node in the document:

```auto
// first get the index of the current node at the root level
const parentIndex = $cursor.index(0);

// iterate the doc to find the offset of the previous index
let startPos, endPos;

doc.forEach((node, offset, index) => {
    if (index === parentIndex - 1) {
        startPos = offset;
        endPos = offset + node.nodeSize;
    }
});

```

Or to get the positions of the last child of the previous block:

```auto
doc.forEach((node, offset, index) => {
    if (index === parentIndex - 1) {
        node.forEach((childNode, childOffset, childIndex) => {
            if (childIndex === node.childCount - 1) {
                startPos = offset + childOffset;
                endPos = startPos + node.nodeSize;
            }
        })
    }
});

```

I tried many attempts which all ended up using `node.eq(anotherNode)` to determine if I had “found” the node I was interested in, but as @marijn has stated this is a bad idea. When iterating it’s possible you could get a different node if these are identical.

I also tried resolving positions inside a node (other than the document) but this was useless. All transforms require absolute global positions and I couldn’t find a way to “translate” a local position to a global one.

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [December 10, 2020, 6:58am UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/6 "2020-12-10T06:58:52Z")

</div>

You don’t need `forEach` to get at a child at a given index, you can just use the `child` or `maybeChild` methods.

---

<div class="post-metadata">

**Author:** ![Pier](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/pier/32/616_2.png) [@Pier](https://discuss.prosemirror.net/u/Pier)\
**Post date:** [December 10, 2020, 3:56pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/7 "2020-12-10T15:56:07Z")

</div>

But then how do you get the offset/pos?

AFAIK the only way to get the offset/pos is by using `forEach()`, `nodesBetween()`, or `descendants()`.

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [December 10, 2020, 4:29pm UTC](https://discuss.prosemirror.net/t/approaches-for-finding-the-position-of-nodes/3333/8 "2020-12-10T16:29:17Z")

</div>

Ah, that’s a good point. There’s a [`posAtIndex`](https://prosemirror.net/docs/ref/#model.ResolvedPos.posAtIndex) helper on resolved positions, but that only helps if you have one of those going through the node.
