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.