Using execCommand (Javascript) to copy hidden text to clipboard
I'm trying to copy to clipboard without using Flash, I plan to fall back onto Flash with the use of ZeroClipboard if the browser is incompatible with the javascript approach.
I have an onClick listener for the button which looks like:
$(buttonWhereActionWillBeTriggered).click(function(){
var copyDiv = document.getElementById(inputContainingTextToBeCopied);
copyDiv.focus();
document.execCommand('SelectAll');
document.execCommand("Copy", false, null);
}
and an input field as follows:
<input type="text" name="Element To Be Copied" id="inputContainingTextToBeCopied" value="foo"/>
This currently works as expected but the design requires that the field containing the text to be copied is invisible. I have tried both setting type="hidden"
and style="display: none"
neither of which have succeeded. Both result in the button selecting the whole page and copying the whole content to the user's clipboard.
I'm relatively confident the cause is not browser-based but just in case, I am testing on Chrome (Version 43.0.2357.134 (64-bit)) on Mac OS X 10.10.4.
Is there a way that I can maintain the functionality of when the < input> is visible whilst hiding it? or if not an alternate route I can take?
I'm aware of similar questions, none of which address my problem, either from being too old, not actually using Javascript, or not fitting the particular scenario. Here's a good answer for anyone having similar, less specific issues.
Solution 1:
Here's my solution that doesn't use jQuery:
function setClipboard(value) {
var tempInput = document.createElement("input");
tempInput.style = "position: absolute; left: -1000px; top: -1000px";
tempInput.value = value;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
}
<!DOCTYPE html>
<html>
<head>
<title>Set Clipboard</title>
</head>
<body>
<button onclick="setClipboard('foo loves bar')">Set Clipboard</button>
</body>
</html>
Solution 2:
2019 - was still looking for an answer without offscreen stuff.
What I did is first change the input text field to type="text", copy the text and then change it back to type="hidden". That works well.
<input id="dummy" name="dummy" type="hidden">
<script>
var copyText = document.getElementById("dummy");
copyText.type = 'text';
copyText.select();
document.execCommand("copy");
copyText.type = 'hidden';
</script>
Solution 3:
--Update--
Document.execCommand()
[1] Before Firefox 41, clipboard capability needed to be enabled in the user.js preference file. See A brief guide to Mozilla preferences for more information. If the command wasn't supported or enabled, execCommand was raising an exception instead of returning false. In Firefox 41 and later, clipboard capability is enabled by default in any event handler that is able to pop-up a window (semi-trusted scripts).
Since Firefox version 41 Document.execCommand() now works. So no need to use a fallback anymore.
Since browsers seem to behave differently when it comes to clipboard access, it took me a while to get my head around it.
It's pretty similar to your solution, but the difference is to create a temporary element and fill it with the input value
. That way we can keep the input's display
property set to none
.
There is also a workaround for IE which uses window.clipboardData
.
Firefox would not let me access the clipboard at all. So I had to add a prompt
to let users manually copy the input value. Sure a prompt
is ugly, but you could just use a modal like a window, which would do the same.
Since this seems to be a knotty thing, I am on Win7 (64 bit) and tested in
Chrome - Version 43.0.2357.134 m
IE - Version 11.0.9600.17914
and Firefox is irrelevant because it would not let me access it anyway.
var copyBtn = $("#copy-btn"),
input = $("#copy-me");
function copyToClipboardFF(text) {
window.prompt ("Copy to clipboard: Ctrl C, Enter", text);
}
function copyToClipboard() {
var success = true,
range = document.createRange(),
selection;
// For IE.
if (window.clipboardData) {
window.clipboardData.setData("Text", input.val());
} else {
// Create a temporary element off screen.
var tmpElem = $('<div>');
tmpElem.css({
position: "absolute",
left: "-1000px",
top: "-1000px",
});
// Add the input value to the temp element.
tmpElem.text(input.val());
$("body").append(tmpElem);
// Select temp element.
range.selectNodeContents(tmpElem.get(0));
selection = window.getSelection ();
selection.removeAllRanges ();
selection.addRange (range);
// Lets copy.
try {
success = document.execCommand ("copy", false, null);
}
catch (e) {
copyToClipboardFF(input.val());
}
if (success) {
alert ("The text is on the clipboard, try to paste it!");
// remove temp element.
tmpElem.remove();
}
}
}
copyBtn.on('click', copyToClipboard);
#copy-me {
display:none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="Element To Be Copied" id="copy-me" value="foo loves bar"/>
<button id="copy-btn">Copy</button><br/><br/>
<textarea placeholder="paste here"></textarea>