Search code examples
javascriptselection

How to get the current text selection with Javascript on ANY part of the website?


I'd like to get the selected text from a website, but when I use document.getSelection it does not work for selections inside textareas and to get the selection from a text area I would need to know which textarea has the selection to use the textarea functions. Is there a simple methods for getting the current selection or do I need to iterate over all elements to test if they contain selected text?


Solution

  • Selection of text in general document content and in user input elements are mutually exclusive.

    • HTMLTextAreaElement and HTMLInputElement both have selectionStart and selectionEnd properties which are offsets of selected text in their content

    • INPUT elements which don't support selection return null for the selection start/end properties.

    • If selectionStart and selectionEnd have the same value there is no selection within the element, and if the values are numeric it give the position of the cursor in the element.

    • If you click elsewhere on the page, INPUT and TEXTAREA elements lose focus and and any selected text in their content is deselected.

    • document.activeElement holds a reference to the currently focused element. A null value indicates the user has clicked outside web page content in the browser, possibly to change tabs. The tagName property of a non-null activeElement indicates what kind of element it is in upper case.

    Putting all of this together I would start with a function similar to that below - it returns null if the page if the not in focus or an INPUT element that doesn't support selection is in focus. Otherwise it returns one of two types of object: either a selection object or a custom object containing details of user input with a type property set to "UIText".

    function getCurrentSelection() {
      let selection;
    
      const active = document.activeElement;
      if(!active) return null;
    
      let tagName = active.tagName;
      if( tagName == "INPUT" || tagName == "TEXTAREA") {
        const {selectionStart, selectionEnd} = active;
        selection = selectionStart === null ? null : {
         type: "UIText",
         element: active,
         tag: tagName,
         selectionStart,
         selectionEnd,
         text: active.value.substring(selectionStart, selectionEnd)
        };
       }
       else {
          selection = document.getSelection()
       }
       return selection;
    }