content icon indicating copy to clipboard operation
content copied to clipboard

Collapse selection after paste

Open kamerat opened this issue 3 years ago • 3 comments

Description

Normal browser behaviour does not highlight text like the example does. Collapsing the selection to end makes the paste seem more natural.

Motivation

I needed this functionality myself, but when trying the example in my own code, i needed to find out how to not make the pasted content selected due to it being a behaviour that's not expected when pasting normally. Having this here would save some googling for other developers.

Additional details

Related issues and pull requests

kamerat avatar Sep 30 '22 19:09 kamerat

I don't know this API too well so I don't understand why this is in the example: https://github.com/mdn/content/blob/3f97a039cb889b2dc7277f5be75904dd739c2c25/files/en-us/web/api/element/paste_event/index.md?plain=1#L74

I have tried without and it seems there's no issues not having it here.

Does anybody know the meaning of this line? If it is needed, a comment would be nice explaining why it's needed for people like myself, otherwise, maybe it can be removed?

kamerat avatar Sep 30 '22 19:09 kamerat

Preview URLs

(this comment was updated 2022-11-14 14:17:41.476351)

github-actions[bot] avatar Oct 04 '22 10:10 github-actions[bot]

I have tried without and it seems there's no issues not having it here.

In *typical* code this is fine, because if the user hasn't clicked on the page, the paste event can't be fired on the target element anyway. But I like the code being defensive—otherwise the selection.getRangeAt(0) call below may throw. Here's a contrived example:

<div class="source" contenteditable="true">Copy text from this box.</div>
<div class="target" contenteditable="true">And paste it into this one.</div>
<script>
  const target = document.querySelector("div.target");

  target.addEventListener("paste", (event) => {
    event.preventDefault();

    console.log(event);
    let paste = (event.clipboardData || window.clipboardData).getData("text");
    paste = paste.toUpperCase();
    const selection = window.getSelection();
    // if (!selection.rangeCount) return;
    selection.deleteFromDocument();
    selection.getRangeAt(0).insertNode(document.createTextNode(paste));
    selection.collapseToEnd();
  });
  const data = new DataTransfer();
  data.setData("text/plain", "Hello world");
  target.dispatchEvent(new ClipboardEvent("paste", { clipboardData: data }));
</script>

This throws: DOMException: Failed to execute 'getRangeAt' on 'Selection': 0 is not a valid index.

But I'll let @Elchi3 review this

Josh-Cena avatar Nov 08 '22 05:11 Josh-Cena