Reputation: 6017
I am trying to copy csv based data (from SlickGrid), in to system clipboard. For small chunks of data it is working fine, but when I have large set of data it is unable to copy into system clipboard.
Here is the code use to perform copy:
copyTextToClipboard: function (text) {
var textArea = document.createElement('textarea');
// Hide textArea
textArea.style.position = 'fixed';
textArea.style.top = 0;
textArea.style.left = 0;
textArea.style.width = '2em';
textArea.style.height = '2em';
textArea.style.padding = 0;
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
textArea.style.background = 'transparent';
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
alert('Oops, unable to copy to clipboard');
}
document.body.removeChild(textArea);
}
When I pass large csv based text into function, I always get:
'Copying text command was unsuccessful'
Sample CSV based text passed into 'copyTextToClipboard' function which fails to copy in clipboard
Another interesting thing here, is when I use Developer tool and step over each line it properly copies the same data into Clipboard.
Upvotes: 0
Views: 1939
Reputation: 43880
The reason why it fails normally and in console it gives partial results is because the input is more than one line. Your function is made to accept a normal string without line breaks. I would assume before ES6 you'd have to insert the line breaks with a backslash \n+
manually or programmatically.
Assuming that you don't care about IE (see caniuse) ES6 Template Literals takes the humble String to a whole new level. The features used in the following demo are:
// Conventional String var str = "These words are 3 spaces apart"; // Template Literal var tl = `These words are 3 spaces apart`
var x = 123; // Conventional String var str = "Height: " + x + "px"; // Template Literal var tl = `Height: ${x}px`;
// Conventional String var str = "\n+" "Multiple\n+" "lines\n"; // Template Literal var tl = ` Multiple lines
Wrap string in backticks: ` (top left corner of keyboard) instead of quotes: " or '
Wrap variables with ${}
instead of "+ +"
Just use the enter key instead of \n+
textarea {
width: 90%;
min-height: 100px;
margin: 10px;
border: 2px solid black;
font: inherit;
}
button {
float: right;
margin-right: 10%
}
<!DOCTYPE html>
<html>
<head>
<style>
body {
font: 400 13px/1.428 Consolas;
}
/* This is just to make the console
|| display data that needs no horizontal
|| scrolling to read.
*/
.as-console {
word-break: break-word;
}
button {
margin-left: 18ch;
}
</style>
</head>
<body>
<ol>
<li>Enter text with line breaks.✎</li>
<li>Click the <kbd>DONE</kbd> button</li>
<li>Next do one of the following:
<ul>
<li>Open a text editor (like Notepad)</li>
<div>OR</div>
<li>Go to the auxiliary demo on this answer</li>
</ul>
<li>Paste into the text editor or the aux demo</li>
</ol>
<p>✎ or you can use a <a href='https://pastebin.com/VZ6Vk4py' target='_blank'>
delimited text file (CSV) of 26 columns and 1000 rows
</a> (right click and open new tab.)</p>
<textarea id='TA'></textarea>
<br/>
<button>DONE</button>
<br/>
<script>
// Reference the <textarea>
var TA = document.getElementById('TA');
/* Register #TA to the change event
|| After the user has typed in #TA
|| and then clicks elsewhere
|| (like the inert <button>)...
*/
TA.addEventListener('change', function(e) {
/* ... the callback function is invoked and
|| the value of the changed element
|| (i.e. e.target = #TA) is passed thru.
*/
copyTextToClipboard(e.target.value);
});
// Define callback function
function copyTextToClipboard(text) {
// Create a <textarea>
var textArea = document.createElement('textarea');
// Hide new <textarea>
textArea.style.opacity = 0;
// Append new <textarea> to the <form>
document.body.appendChild(textArea);
/* Wrap the data in backticks:`
|| (key is top left corner of keyboard)
|| and the variable of data in a dollar
|| sign and curly brackets: ${}
|| The data (a string), is now an
|| ES6 template literal.
*/
var str = `${text}`;
// Assign the new <textArea> value to str
textArea.value = str;
/* .select() method gets the content of
|| new <textarea>
*/
textArea.select();
/* copy the selected text to the OS
|| clipboard.
*/
document.execCommand('copy');
console.log(str);
}
</script>
</body>
</html>
body {
font: 400 13px/1.428 Consolas
}
textarea {
width: 90%;
min-height: 250px;
margin: 10px;
border: 2px solid black;
font: inherit;
}
<textarea placeholder='Paste text in this textarea'></textarea>
Upvotes: 1