0

An MUI Menu (PopOver) is open with a MenuItem for 'Copy to Clipboard' Option. The MenuItem has an <IconButton>. The onClick handler for the IconButton invokes document.execCommand('copy').

The code for CopyToClipBoard is as follows Ref: How do I copy to the clipboard in JavaScript?

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  
  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}

This snippet worked perfectly in other pages with no React MUI popovers. However, it never worked with a page where an MUI popover was open.

After some googling, I found that the popovers are auto focus. Ref: Prevent auto focus of a material-ui popover element

The workaround I have now is to temporarily hide the popovers and re-enable them after copying the text to clipboard.

const fallbackCopyTextToClipboard = text => {
  let textArea = document.createElement('textArea');
  textArea.value = text;

  // Avoid scrolling to bottom
  textArea.style.top = '0';
  textArea.style.left = '-9999'; //Hide from view
  textArea.style.position = 'fixed';
  textArea.style['z-index'] = '9999'; //Bring this infront of all possible popovers

  //This is a hack
  //Momentarily hide all popovers to give focus() to the temporary <textarea>
  const allPopOvers = document.getElementsByClassName('MuiPopover-root');
  const openPopOvers = [];
  for (let popover of allPopOvers) {
    if (popover.style.visibility !== 'hidden') {
      openPopOvers.push(popover);
      popover.style.visibility = 'hidden';
    }
  }
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  let successful = false;
  try {
    successful = document.execCommand('copy');
    //Undo the changes to visible popovers
    openPopOvers.forEach(popover => {
      popover.style.visibility = '';
    });
  } catch (err) {
    logger.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
  return successful;
};

If someone has come across the same issue, please suggest a fix that worked for you.

Ouroborus
  • 12,316
  • 1
  • 27
  • 51
  • Today we have the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API). – Ouroborus Jan 22 '21 at 04:22
  • Yeah. But looks like Clipboard API is not available over 'http'. It works on 'https'. – tasubha Feb 23 '21 at 17:51
  • A good chunk of the newer features require `https`. There's no good reason these days to have a site available via `http`. – Ouroborus Feb 23 '21 at 23:48

0 Answers0