Ok so feels like i have gone down a rabbit hole of how to copy text to clipboard on here and tried a lot of suggestions
seems easy to do it for chrome but that option doesn't work in other browsers
I have a few requirements
I would like to copy text to clipboard
to be able to copy a section of html with multiple elements
To work in safari and chrome at least
Vanilla Javascript
I have found this solution and it works except that it copies the html tags as well?
i tried changing the .innerHTML to .value on the button, but that comes back undefined
<div id="something">
<div>first name: <span class="name">name</span></div>
<div>Job title: <span class="job">job</span></div>
<div>Phone number: 0123456789</div>
<img class="companylogo" src="./img/example.jpg">
</div>
<button onclick="copyToClipboard(document.getElementById('something').innerHTML)">
Copy the stuff
</button>
<script>
/* copy function */
function copyToClipboard(textToCopy) {
var textArea;
function isOS() {
//can use a better detection logic here
return navigator.userAgent.match(/ipad|iphone/i);
}
function createTextArea(text) {
textArea = document.createElement('textArea');
textArea.readOnly = true;
textArea.contentEditable = true;
textArea.value = text;
document.body.appendChild(textArea);
}
function selectText() {
var range, selection;
if (isOS()) {
range = document.createRange();
range.selectNodeContents(textArea);
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
textArea.setSelectionRange(0, 999999);
} else {
textArea.select();
}
}
function copyTo() {
document.execCommand('copy');
document.body.removeChild(textArea);
}
createTextArea(textToCopy);
selectText();
copyTo();
}
</script>
document.getElementById('something').innerHTML
sends html code inside #something to copyToClipboard and this behavior you mentiond is expected . what do you want to be copied to clipboard if not html ?
thanks Hosseind600 for trying to help
but i managed to find some code that does exactly what i would like it to do. whilst ticking off the requirements i had set
its currently the second answer but highest votes
How to copy text from a div to clipboard
<html>
<body>
<div id="a" onclick="copyDivToClipboard()"> Click to copy </div>
<script>
function copyDivToClipboard() {
var range = document.createRange();
range.selectNode(document.getElementById("a"));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
}
</script>
</body>
</html>
Related
I'm running a script to sanitize pasted text in a div with contenteditable.
It's working pretty good, but in FF the line-breaks are removed if the text is copied to the same or between the divs.
Any solution for that?If I paste text from a different source the line-breaks are intact.
I'm also open to different solutions than the one below.
// Paste fix for contenteditable
$(document).on('paste', '[contenteditable]', function (e) {
e.preventDefault();
if (window.clipboardData) {
content = window.clipboardData.getData('Text');
if (window.getSelection) {
var selObj = window.getSelection();
var selRange = selObj.getRangeAt(0);
selRange.deleteContents();
selRange.insertNode(document.createTextNode(content));
}
} else if (e.originalEvent.clipboardData) {
content = (e.originalEvent || e).clipboardData.getData('text/plain');
document.execCommand('insertText', false, content);
}
});
div {
white-space: pre-wrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one below. Where do they line-breaks go in FF?</div>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one above. Where do they line-breaks go FF?</div>
As promised, here is a working solution of such implementation discussed in question's comments.
While working with Selection and Range API (https://developer.mozilla.org/en-US/docs/Web/API/Range), i found that Range object has a toString() method and i thought to test it to see if newlines were trimmed here, before, or later.
Fortunatly, i found out that the toString() method in FF Range object doesn't trim out newlines.
According to that, here is my code and fiddle to override default copy function, overwriting (on copy event) what's inside the clipboard.
$(document).on('copy', '[contenteditable]', function (e) {
e = e.originalEvent;
var selectedText = window.getSelection();
console.log("original copied text\n--------\n", selectedText.toString());
var range = selectedText.getRangeAt(0);
var selectedTextReplacement = range.toString()
console.log("replacement in clipboard\n--------\n", selectedTextReplacement);
e.clipboardData.setData('text/plain', selectedTextReplacement);
e.preventDefault(); // default behaviour is to copy any selected text
});
// Paste fix for contenteditable
$(document).on('paste', '[contenteditable]', function (e) {
e.preventDefault();
if (window.clipboardData) {
content = window.clipboardData.getData('Text');
if (window.getSelection) {
var selObj = window.getSelection();
var selRange = selObj.getRangeAt(0);
selRange.deleteContents();
selRange.insertNode(document.createTextNode(content));
}
} else if (e.originalEvent.clipboardData) {
content = (e.originalEvent || e).clipboardData.getData('text/plain');
document.execCommand('insertText', false, content);
}
});
div {
white-space: pre-wrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one below. Where do they line-breaks go in FF?</div>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one above. Where do they line-breaks go FF?</div>
I also made rough test with edge and chrome, and that override "doesn't mess them up", so maybe you can keep it to have control over what they are doing when something is copied.
At the end of all, i still have a question that keeps yelling in my mind and it is:
Why use contenteditable div instead of textarea if you don't want html into your frontend element?
Here is my code for when the user clicks on this button:
<button id="button1">Click to copy</button>
How do I copy the text inside this div?
<div id="div1">Text To Copy</div>
I tried the solution proposed above. But it was not cross-browser enough. I really needed ie11 to work.
After trying I got to:
<html>
<body>
<div id="a" onclick="copyDivToClipboard()"> Click to copy </div>
<script>
function copyDivToClipboard() {
var range = document.createRange();
range.selectNode(document.getElementById("a"));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
}
</script>
</body>
</html>
Tested with firefox 64, Chrome 71, Opera 57, ie11(11.472.17134.0), edge( EdgeHTML 17.17134)
Update March 27th, 2019.
For some reason document.createRange() didn't work before with ie11. But now properly returns a Range object. So is better to use that, rather than document.getSelection().getRangeAt(0).
Both examples work like a charm :)
JAVASCRIPT:
function CopyToClipboard(containerid) {
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select().createTextRange();
document.execCommand("copy");
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(containerid));
window.getSelection().addRange(range);
document.execCommand("copy");
alert("Text has been copied, now paste in the text-area")
}
}
<button id="button1" onclick="CopyToClipboard('div1')">Click to copy</button>
<br /><br />
<div id="div1">Text To Copy </div>
<br />
<textarea placeholder="Press ctrl+v to Paste the copied text" rows="5" cols="20"></textarea>
JQUERY (relies on Adobe Flash):
https://paulund.co.uk/jquery-copy-to-clipboard
The accepted answer does not work when you have multiple items to copy, and each with a separate "copy to clipboard" button. After clicking one button, the others will not work.
To make them work, I added some code to the accepted answer's function to clear text selections before doing a new one:
function CopyToClipboard(containerid) {
if (window.getSelection) {
if (window.getSelection().empty) { // Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) { // Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) { // IE?
document.selection.empty();
}
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select().createTextRange();
document.execCommand("copy");
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(containerid));
window.getSelection().addRange(range);
document.execCommand("copy");
}
}
I was getting selectNode() param 1 is not of type node error.
changed the code to this and its working. (for chrome)
function copy_data(containerid) {
var range = document.createRange();
range.selectNode(containerid); //changed here
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("copy");
window.getSelection().removeAllRanges();
alert("data copied");
}
<div id="select_txt">This will be copied to clipboard!</div>
<button type="button" onclick="copy_data(select_txt)">copy</button>
<br>
<hr>
<p>Try paste it here after copying</p>
<textarea></textarea>
This solution add the deselection of the text after the copy to the clipboard:
function copyDivToClipboard(elem) {
var range = document.createRange();
range.selectNode(document.getElementById(elem));
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand("copy");
window.getSelection().removeAllRanges();
}
<div id='myInputF2'> YES ITS DIV TEXT TO COPY </div>
<script>
function myFunctionF2() {
str = document.getElementById('myInputF2').innerHTML;
const el = document.createElement('textarea');
el.value = str;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
alert('Copied the text:' + el.value);
};
</script>
more info: https://hackernoon.com/copying-text-to-clipboard-with-javascript-df4d4988697f
Here you can see code which works on different browsers, including iOS.
const copyToClipboard = (id) => {
var r = document.createRange();
r.selectNode(document.getElementById(id));
window.getSelection().removeAllRanges();
window.getSelection().addRange(r);
document.execCommand("copy");
window.getSelection().removeAllRanges();
};
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
const copyIOS = (id) => {
const text = document.getElementById(id).innerHTML;
if (!navigator.clipboard) {
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.fontSize = "20px";
document.body.appendChild(textarea);
const range = document.createRange();
range.selectNodeContents(textarea);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
textarea.setSelectionRange(0, 999999);
document.execCommand("copy");
document.body.removeChild(textarea);
}
navigator.clipboard.writeText(text);
};
const copyTextById = (id) => {
if (isIOS) {
return copyIOS(id);
}
copyToClipboard(id);
};
window.copyTextById = copyTextById
<div id="text">Text which you will copy</div>
<button onclick="copyTextById('text')">Click me</button>
Adding the link as an Answer to draw more attention to Aaron Lavers' comment below the first answer.
This works like a charm - http://clipboardjs.com. Just add the clipboard.js or min file. While initiating, use the class which has the html component to be clicked and just pass the id of the component with the content to be copied, to the click element.
Made a modification to the solutions, so it will work with multiple divs based on class instead of specific IDs. For example, if you have multiple blocks of code. This assumes that the div class is set to "code".
<script>
$( document ).ready(function() {
$(".code").click(function(event){
var range = document.createRange();
range.selectNode(this);
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
});
});
</script>
Non of all these ones worked for me. But I found a duplicate of the question which the anaswer worked for me.
Here is the link
How do I copy to the clipboard in JavaScript?
The solutions above do not work for the content editable div. A few more steps are needed to copy its content to the clipboard.
Here is how to copy div contenteditable to the clipboard. Selecting text on the iphone and Android is not always easy. With one Copy button you can copy all the content.
<div id="editor1" contenteditable="true"></div>
<button id="button1" onclick="CopyToClipboard()">COPY</button>
<script>
function CopyToClipboard() {
var copyBoxElement = document.getElementById('editor1');
copyBoxElement.contenteditable = true;
copyBoxElement.focus();
document.execCommand('selectAll');
document.execCommand("copy");
copyBoxElement.contenteditable = false;
alert("Text has been copied")
}
</script>
I want to automatically select a piece of text so that the user can use ctrl + c to copy it to its clipboard.
In order to do this, I've attached some event handlers to a couple of inputs and a couple of divs (with tabindex="0").
However, if I select a piece of text with javascript, the browser indicates a selection but keeps the focus on the input.
If I try to achieve the same thing but with the div being the trigger, It works.
This behavior is only in FireFox.
In my jsfiddle (or in the snippet below) put the focus on the first input, press a random key (which selects the text), and try to copy paste it in the lower input.
Then try to do the same but with clicking the div. (clicking the div will also select the text).
var input = document.getElementById("my-input");
input.addEventListener("keydown", function(evt){
selectText(document.getElementById("selectme"));
});
var div = document.getElementById("clickme");
div.addEventListener("click", function(evt){
selectText(document.getElementById("selectme"));
});
var selectText = function(element){
var range, selection;
if(document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if(window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
element.focus();
}
<input id="my-input"/>
<div id="selectme">Texttexttexttext</div>
<div tabindex="0" id="clickme">CLICK ME</div>
<input />
If you call evt.target.blur(); first, the input will lose its focus before focussing the div.
Your function will look like:
var input = document.getElementById("my-input");
input.addEventListener("keydown", function(evt){
evt.target.blur();
selectText(document.getElementById("selectme"));
});
I my application i want to make the text seleected selected using mouse bold..How to do this using javascript?
Also how to know the cursor position using javascript...For example ,i may need to insert a text using my function just before the text where cursor is placed
You can do this in a textarea:
<html>
<head>
<title>onselect test</title>
<script type="text/javascript">
window.onselect = selectText;
function selectText(e)
{
start = e.target.selectionStart;
end = e.target.selectionEnd;
alert(e.target.value.substring(start, end));
}
</script>
</head>
<body>
<textarea>
Highlight some of this text
with the mouse pointer
to fire the onselect event.
</textarea>
</body>
</html>
Do you mean something like this:
function getSelText()
{
var txt = '';
if (window.getSelection)
{
txt = window.getSelection();
}
else if (document.getSelection)
{
txt = document.getSelection();
}
else if (document.selection)
{
txt = document.selection.createRange().text;
}
else { return; }
}
//txt is the selected text
Caching selected text, only available when it is editable input, but not in uneditable htm area i.e. when the text in div or span or etc. the above methods dosn't work .
I found this in the js source here: http://www.clae.com/jscripts/common.js
I don't know what this does, does it copy text to the clipboard? i thought it was impossible for JS to copy text to the clipboard?
// Copies passed text to the clipboard
function copyToClipboard(text) {
var range = document.body.createTextRange();
range.findText(text);
range.select();
document.execCommand("Copy");
document.execCommand("Unselect");
}
It's not that cross-browser. Check this out: http://www.quirksmode.org/dom/execCommand.html
This works on IE and FireFox... I tested those today:
MENU ITEM a-tag: onclick="javascript:copyText()"
JAVASCRIPT:
function copyText() {
if(document.all){
// IE - copy the selected text
var selection = document.selection;
var CopiedTxt = selection.createRange();
CopiedTxt.select();
CopiedTxt.execCommand("Copy");
copiedtext=window.clipboardData.getData("Text");
// alert("IE=" + copiedtext);
} else{
// FF - copy the selected text
var start=thisElementObject.selectionStart;
var end=thisElementObject.selectionEnd;
thisSelectedText=thisElementObject.value.substring(start, end);
// alert("FF=" + thisSelectedText);
}
}