1

Need to gather HTML (to strip some of the styling) during the copy event.

Currently, attempting to do the following:

Add a listener for the 'copy' event

document.addEventListener('copy', (e) => {
    console.log("e.target:" + e.target);
});

And then use clipboard api to copy the item Along the lines of:

    var blob = new Blob([html], {type: "text/html"});
    var item = new ClipboardItem({"text/html": blob});
    navigator.clipboard.write([item])

However, when attempting to gather html on copy event I am using e.target to gather the HTML. It appears that e.target.nextElementSibling when called recursively should give the value of the next element. However, when items are selected from a list (without the entire list being selected) it does not appear to work as expected.

As example:

<html>
<head>
<title> The simplest HTML example 
</title>
</head>
<body>
  <h1> This is  an HTML Page </h1>
  <ul>
    <li>
      <a href="https://www.google.com/">goog</a>
    </li>
    <li>
      <a href="https://www.bing.com/">bing</a>  
    </li>
  </ul>
  
  Not in list:
    <a href="https://www.google.com/">goog</a>
    <a href="https://www.bing.com/">bing</a>  

</body>
</html>
document.addEventListener('copy', (e) => {
  console.log("e.target:" + e.target);
  console.log("e.target:" + e.target.nextElementSibling);
});

JSFiddle: https://jsfiddle.net/q8d9vogu/9/

Selecting the Not in list: goog bing shows both of the elements. While selecting the list goog & bing ONLY shows google one (e.target.nextElementSibling is null).

How should we go about gathering the HTML that is copied within the copy event? (context: this is running within VSCode extension)

Mark
  • 143,421
  • 24
  • 428
  • 436
user7858768
  • 838
  • 7
  • 22

1 Answers1

0

Answering my own question with potential solution in case others run into this. The following seems to be doing the trick of grabbing HTML and copying it into clipboard:

    document.addEventListener('copy', (e) => {
          const htmlSelection = getHTMLOfSelection();
          
          if (htmlSelection !== undefined){
            copyToClipboard(htmlSelection);            
          }
      });
      
      /** 
       * Based off of: https://stackoverflow.com/a/5084044/7858768
       * */
      function getHTMLOfSelection () {
        let range;
        if (document.selection && document.selection.createRange) {
          range = document.selection.createRange();
          return range.htmlText;
        }
        else if (window.getSelection) {
          const selection = window.getSelection();
          if (selection.rangeCount > 0) {
            range = selection.getRangeAt(0);
            const clonedSelection = range.cloneContents();
            const div = document.createElement('div');
            div.appendChild(clonedSelection);
            return div.innerHTML;
          }
          else {
            return undefined;
          }
        }
        else {
          return undefined;
        }
      }
      
      /**
      Based off of: 
      * https://stackoverflow.com/a/64711198/7858768
      * https://stackoverflow.com/a/57279336/7858768
      */
      function copyToClipboard(html) {
          
          const container = document.createElement('div');
          container.innerHTML = html;
          container.style.position = 'fixed';
          container.style.pointerEvents = 'none';
          container.style.opacity = 0;
          
          const blob = new Blob([html], {type: "text/html"});
          const item = new ClipboardItem({"text/html": blob});
   
          navigator.clipboard.write([item]).then(function() {
            console.log("Copied to clipboard successfully!");
          }, function(error) {
            console.error("Unable to write to clipboard. Error:");
            console.log(error);
          });
      }
    ```
user7858768
  • 838
  • 7
  • 22