# Expanding the selection to the active mark?

**URL:** https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478
**Category:** Uncategorized
**Created:** [November 4, 2016, 10:24am UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478 "2016-11-04T10:24:31Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![erwanl](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/erwanl/32/221_2.png) [@erwanl](https://discuss.prosemirror.net/u/erwanl)
#### Post date: [November 4, 2016, 10:24am UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/1 "2016-11-04T10:24:31Z")

</div>

Hi,

I’m trying to implement buttons for link, typically remove link and change link destination. Using/patching toggleMark I was able to make it work if the user selects exactly the text that has the link.

However I want to be able to do that when the user when the cursor is in the middle of the link. I think it could be done by modifying the selection to make it match the whole mark before applying the command.

I figured out how to get the active marks, but they come without their positions so I can’t find how to do that. Is there a simple way to do it? Basically get the from/to positions corresponding at the start and end positions of the mark.

---

<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: [November 4, 2016, 1:34pm UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/2 "2016-11-04T13:34:38Z")

</div>

You’ll need to inspect the parent node of the cursor, and find the range that the current link covers in that. You could do something like this (untested):

```javascript
function linkAround(doc, pos) {
  let $pos = doc.resolve(pos), parent = $pos.parent
  let start = parent.childAfter($pos.parentOffset)
  if (!start.node) return null
  let link = start.node.marks.find(mark => mark.type.name == "link")
  if (!link) return null

  let startIndex = $pos.index(), startPos = $pos.start() + start.offset
  while (startIndex > 0 && link.isInSet($pos.child(startIndex - 1).marks))
    startPos -= $pos.child(--startIndex).nodeSize
  let endIndex = $pos.indexAfter(), endPos = startPos + start.node.nodeSize
  while (end < parent.childCount && link.isInSet($pos.child(endIndex).marks))
    endPos += $pos.child(endIndex++).nodeSize
  return {from: startPos, to: endPos}
}

```

---

<div class="post-metadata">

### Author: ![erwanl](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/erwanl/32/221_2.png) [@erwanl](https://discuss.prosemirror.net/u/erwanl)
#### Post date: [November 4, 2016, 3:15pm UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/3 "2016-11-04T15:15:13Z")

</div>

Thank you!

I was able to make it work after a few adaptations (for example it’s not ResolvedPos.child, it’s ResolvedPos.node).

---

<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: [November 4, 2016, 3:30pm UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/4 "2016-11-04T15:30:08Z")

</div>

Oh, those should be `parent.child`, not `$pos.child` (and also not `$pos.node`!)

---

<div class="post-metadata">

### Author: ![erwanl](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/erwanl/32/221_2.png) [@erwanl](https://discuss.prosemirror.net/u/erwanl)
#### Post date: [November 4, 2016, 3:54pm UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/5 "2016-11-04T15:54:03Z")

</div>

I see! I think it was working because in the case I was testing, it wasn’t going in the `while` anyway so the first values were the correct ones.

---

<div class="post-metadata">

### Author: ![mitar](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/mitar/32/375_2.png) [@mitar](https://discuss.prosemirror.net/u/mitar)
#### Post date: [April 2, 2018, 8:28pm UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/6 "2018-04-02T20:28:08Z")

</div>

I have found this and [Find extents of a mark given a selection](https://discuss.prosemirror.net/t/find-extents-of-a-mark-given-a-selection/344). Could this maybe be made into a function in ProseMirror. I am afraid to miss some edge case doing this myself.

---

<div class="post-metadata">

### Author: ![mitar](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/mitar/32/375_2.png) [@mitar](https://discuss.prosemirror.net/u/mitar)
#### Post date: [April 3, 2018, 3:44am UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/7 "2018-04-03T03:44:57Z")

</div>

So based on comments above, this is fixed code. Is this right?

```
function linkAround(doc, pos) {
  let $pos = doc.resolve(pos);

  let start = $pos.parent.childAfter($pos.parentOffset);
  if (!start.node) {
    return;
  }

  let link = start.node.marks.find((mark) => mark.type === this.$editorView.state.schema.marks.link);
  if (!link) {
    return;
  }

  let startIndex = $pos.index();
  let startPos = $pos.start() + start.offset;
  while (startIndex > 0 && link.isInSet($pos.parent.child(startIndex - 1).marks)) {
    startIndex -= 1;
    startPos -= $pos.parent.child(startIndex).nodeSize;
  }

  let endIndex = $pos.indexAfter();
  let endPos = startPos + start.node.nodeSize;
  while (endIndex < $pos.parent.childCount && link.isInSet($pos.parent.child(endIndex).marks)) {
    endPos += $pos.parent.child(endIndex).nodeSize;
    endIndex += 1;
  }

  return {from: startPos, to: endPos};
}
```

---

<div class="post-metadata">

### Author: ![rsdrsd](https://discuss.prosemirror.net/letter_avatar_proxy/v4/letter/r/76d3ee/32.png) [@rsdrsd](https://discuss.prosemirror.net/u/rsdrsd)
#### Post date: [January 25, 2019, 7:15pm UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/8 "2019-01-25T19:15:04Z")

</div>

I am also looking for a solution like this. So if the cursor is on a link or a single link is fully selected, then it is editable. In current example it is not clear which url it is.

---

<div class="post-metadata">

### Author: ![rowanc1](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/rowanc1/32/1341_2.png) [@rowanc1](https://discuss.prosemirror.net/u/rowanc1)
#### Post date: [December 1, 2020, 6:52am UTC](https://discuss.prosemirror.net/t/expanding-the-selection-to-the-active-mark/478/9 "2020-12-01T06:52:27Z")

</div>

I was testing this out on links that had bold/italics etc in them. This I believe handles those cases. The implementations above don’t work for me due to the `endIndex` first calculation in some placements of the cursor (directly after bold in a link?). Hope this maybe helps someone else … !

```auto
function linkAround(state, pos) {
  const $pos = state.doc.resolve(pos);

  const { parent, parentOffset } = $pos;
  const start = parent.childAfter(parentOffset);
  if (!start.node) return null;

  const link = start.node.marks.find((mark) => mark.type === state.schema.marks.link);
  if (!link) return null;

  let startIndex = $pos.index();
  let startPos = $pos.start() + start.offset;
  let endIndex = startIndex + 1;
  let endPos = startPos + start.node.nodeSize;
  while (startIndex > 0 && link.isInSet(parent.child(startIndex - 1).marks)) {
    startIndex -= 1;
    startPos -= parent.child(startIndex).nodeSize;
  }
  while (endIndex < parent.childCount && link.isInSet(parent.child(endIndex).marks)) {
    endPos += parent.child(endIndex).nodeSize;
    endIndex += 1;
  }
  return { from: startPos, to: endPos };
}

```
